美文网首页
LeetCode 刷题总结(9)

LeetCode 刷题总结(9)

作者: Jingtianer | 来源:发表于2019-02-23 22:53 被阅读0次

92. 反转链表 II

思路

  1. 两个指针a、b,分别找到被反转的第一个结点的前一个结点,被反转的结点的最后一个结点,(在开头设置一个哑结点,防止被反转的第一个结点是头结点)
  2. 再来一个指针c,保存被反转的最后一个结点的next,然后把最后一个结点的next设为null
  3. 反转链表,然后把新链表的head接回去,把c接回到末尾
  4. 返回哑结点的next,不能返回head,因为反转以后,head有可能不是head了

AC代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode* dummy = new ListNode(0), *a, *b, *c;
        dummy->next = head;
        a = b = c = dummy;
        for (int i = 0; i < m - 1; i++) {
            a = a->next;
            b = b->next;
        }
        for (int i = 0; i < n - m + 1; i++) {
            b = b->next;
        }
        c = b->next;
        b->next = NULL;
        a->next = reverseList(a->next);
        while (a->next != NULL) {
            a = a->next;
        }
        a->next = c;
        return dummy->next;
    }
    ListNode* reverseList(ListNode* head) {
        if (head == NULL || head->next == NULL) return head;
        ListNode *temp = reverseList(head->next);
        head->next->next = head;
        head->next = NULL;
        return temp;
    }
};

15. 三数之和

思路

  1. 遍历数组,取每个值的相反数作为target,然后转化为两数之和的问题,去重时要注意
    1. 保证target只查找一次
    2. 保证第二个循环j = i + 1开始
    3. 保证查找到的数的下标 c > j
    4. 保证第二次循环的相同元素对应的值不会被反复查找,即变量find

AC代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int len = nums.size();
        vector<vector<int>> ans;
        map<int, int> m;
        for (int i = 0; i < len; i++) {
            m[nums[i]] = i + 1;
        }
        for (int i = 0; i < len; ) {
            int target = -nums[i];
            for (int j = i + 1; j < len;) {
                int find = target - nums[j];
                if (m.count(find)) {
                    int c = m[find] - 1;
                    //cout << nums[i] << nums[j] << nums[c] << endl;
                    if (c > j) {
                        ans.push_back({nums[i], nums[j], nums[c]});
                    }
                }
                while (j < len && nums[j] == target - find) {
                    j++;
                }
            }
            while (i < len && nums[i] == -target) {
                i++;
            }
        }
        return ans;
    }
};

大佬思路

二分查找

大佬代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        set<vector<int>> ans;
        if(nums.size()<3)return vector<vector<int>>(ans.begin(),ans.end());
        sort(nums.begin(),nums.end());
        int left,right,target;
        for(int i=0;i<nums.size()-2;++i){
            if(nums[i] > 0)
            {
                break;
            }
            if(nums[i] == nums[i - 1] && i > 0)
               continue;
            left=i+1,right=nums.size()-1,target=-nums[i];
            while(left<right){
                if(nums[left]+nums[right]==target){
                    ans.insert({nums[i], nums[left], nums[right]});
                    ++left;
                    --right;
                }else if(nums[left]+nums[right]>target){
                    --right;
                }else {
                    ++left;
                }
            }
        }
        return vector<vector<int>>(ans.begin(),ans.end());
    }
};

43. 字符串相乘

思路

两层for循环相乘,把相乘的结果全都加起来

AC代码

class Solution {
public:
    string multiply(string num1, string num2) {
        int len1 = num1.length(), len2 = num2.length();
        int len = len1 > len2 ? len1 : len2;
        string zero(len - len1, '0');
        num1 = zero + num1;
        zero = string(len - len2, '0');
        num2 = zero + num2;
        string ans = "0";
        for (int i = len - 1; i >= 0; i--) {
            string temp = num1;
            int carry = 0;
            zero = string(len - 1 - i, '0');
            for (int j = len - 1; j >= 0; j--) {
                temp[j] = ((num1[j] - '0')*(num2[i] - '0') + carry)%10+ '0';
                carry = ((num1[j] - '0')*(num2[i] - '0') + carry)/10;
            }
            temp = string(1, carry + '0') + temp + zero;
            ans = addStrings(ans, temp);
            
        }
        int i = 0;
        while (ans[i] == '0') i++;
        len = ans.length();
        return i == len ? "0" : ans.substr(i, len - i);
    }
    string addStrings(string& num1, string& num2) {
        int carry = 0;
        int len1 = num1.length();
        int len2 = num2.length();
        int len = len1 > len2 ? len1 : len2;
        string zero = string(len - len1, '0');
        num1 = zero + num1;
        zero = string(len - len2, '0');
        num2 = zero + num2;
        for (int i = len - 1; i >= 0; i--) {
            int n = carry + num1[i] + num2[i] - 2*'0';
            num1[i] = n % 10 + '0';
            carry = n / 10;
        }
        if (carry) num1.insert(0, 1, carry + '0');
        return num1;
    }
};

73. 矩阵置零

思路

想写出来很简单,目前是空间O(M+N)的算法

AC代码

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int r = matrix.size(), c = matrix[0].size();
        unordered_map<int, bool> rows, cols;
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                if (matrix[i][j] == 0) {
                    rows[i] = true;
                    cols[j] = true;
                }
            }
        }
        for (auto x : rows) {
            for (int i = 0; i < c; i++) {
                matrix[x.first][i] = 0;
            }
        }
        for (auto x : cols) {
            for (int i = 0; i < r; i++) {
                matrix[i][x.first] = 0;
            }
        }
    }
};

60. 第k个排列

思路

没研究这个,stl直接调用

AC代码

class Solution {
public:
    string getPermutation(int n, int k) {
        string ans;
        for (int i = 1; i <= n; i++) {
            ans += char(i + '0');
        }
        for (int i = 0; i < k - 1; i++) {
            next_permutation(ans.begin(), ans.end());
        }
        return ans;
    }
};

大佬代码

static const auto io_sync_off = []()
{
    // turn off sync
    std::ios::sync_with_stdio(false);
    // untie in/out streams
    std::cin.tie(nullptr);
    return nullptr;
}();

class Solution {
public:
    string recursive(int n, int k, int * order, string &str) {
        if (n == 0)
            return "";
        int num = (k - 1) / order[n - 1];
        char c = str[num];
        str.erase(str.begin() + num);
        return c + recursive(n - 1, k - num * order[n - 1], order, str);
    }
    
    string getPermutation(int n, int k) {
        int order[n + 1] = {1};
        string str;
        for (int i = 1; i < n + 1; i++) {
            order[i] = i * order[i - 1];
            str.push_back(48 + i);            
        }
        return recursive(n, k, order, str);
    }
};

34. 在排序数组中查找元素的第一个和最后一个位置

思路

一次二分查找,然后向前向后遍历,找到开始和结束,但是最坏情况下,算法从O(log_2n)变成O(n)

AC代码

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int len = nums.size();
        if (!len) return {-1, -1};
        int low = 0, high = len - 1;
        bool find = false;
        int pos = 0;
        while (low <= high) {
            int mid = low + (high - low)/2;
            if (nums[mid] == target) {
                find = true;
                pos = mid;
                break;
            } else if (nums[mid] > target) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        if (!find) {
            return {-1, -1};
        }
        int beg , end;
        beg = end = pos;
        while (beg >= 0 && nums[pos] == nums[beg]) beg--;
        while (end < len && nums[pos] == nums[end]) end++;
        return {beg + 1, end - 1};
    }
};

24. 两两交换链表中的节点

AC代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode dummy(0), *h;
        dummy.next = head;//哑结点定义为局部变量,防止内存泄漏
        h = &dummy;
        while (h->next != NULL) {
            if (h->next->next != NULL) {
                ListNode *a = h->next, *b = h->next->next;
                a->next = b->next;
                b->next = a;
                h->next = b;
                h = h->next->next;
            } else {
                break;
            }
        }
        return dummy.next;
    }
};

47. 全排列 II

AC代码

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> ans;
        do {
            ans.push_back(nums);
        }while (next_permutation(nums.begin(), nums.end()));
        ans.erase(unique(ans.begin(), ans.end()),ans.end());
        return ans;
    }
};

大佬代码

class Solution {
public:
    vector<vector<int>> ans;
    vector<bool> b;
    vector<int> v;
    void dfs(int i, const vector<int>& nums)
    {
        if(i == nums.size()){
            ans.push_back(v);
            return;
        }
        for(int j = 0; j < nums.size(); ++j){
            if(j > 0 && nums[j - 1] == nums[j] && !b[j - 1])continue;
            if(!b[j]){
                b[j] = 1;
                v[i] = nums[j];
                dfs(i + 1, nums);
                b[j] = 0;
            }
        }
        return;
    }
    
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        v.resize(nums.size());
        b.resize(nums.size());
        dfs(0, nums);
        return ans;
    }
};

49. 字母异位词分组

思路

  1. stl使劲套,要用multiset,两个单词字符集相同但是字符个数不同
  2. 优化,不用set,map变成string,字符集的字符串排序后对应唯一的“特征字符串”

AC代码

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        map<multiset<char>, vector<string>> m;
        int num = strs.size();
        for (auto &x : strs) {
            multiset<char> s(x.begin(), x.end());
            m[s].push_back(x);
        }
        vector<vector<string>> ans;
        for (auto &x : m) {
            ans.push_back(x.second);
        }
        return ans;
    }
};
static const auto io_sync_off = []() {
    // turn off sync
    std::ios::sync_with_stdio(false);
    // untie in/out streams
    std::cin.tie(nullptr);
    return nullptr;
}();

AC代码(优化)

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> m;
        for (auto &x : strs) {
            string temp = x;
            sort(x.begin(), x.end());
            m[x].push_back(temp);
        }
        vector<vector<string>> ans;
        for (auto &x : m) {
            ans.push_back(x.second);
        }
        return ans;
    }
};

80. 删除排序数组中的重复项 II

思路

双指针

遍历一遍数组,

AC代码

class Solution {
  public:
    int removeDuplicates(vector<int> &nums) {
        int i = 0, j = 0;
        int len = nums.size();
        while (i < len) {
            if (j < 2 || nums[i] > nums[j - 2]) {
                int n = nums[i];
                nums[j++] = n;
            }
            i++;
        }
        return j;
    }
};

相关文章

网友评论

      本文标题:LeetCode 刷题总结(9)

      本文链接:https://www.haomeiwen.com/subject/jfvmyqtx.html