LeetCode 刷题总结(9)

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;
    }
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容