LeetCode Hot 100记录(19/100)

哈希(3/3)

给定一个整数数组  nums  和一个整数目标值  target,请你在该数组中找出  和为目标值 target  的那  两个  整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> mp;
        int n = nums.size();
        for (int i = 0; i < n; i++) {
            if (mp.count(target - nums[i])) {
                return {mp[target - nums[i]], i};
            }
            mp[nums[i]] = i;
        }
        return {};
    }
};

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> mp;
        for (auto& s : strs) {
            string t = s;
            sort(t.begin(), t.end());
            mp[t].push_back(s);
        }
        vector<vector<string>> v;
        for (auto& i : mp) {
            v.push_back(move(i.second));
        }
        return v;
    }
};

给定一个未排序的整数数组  nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为  O(n)  的算法解决此问题。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        if (nums.empty())
            return 0;
        if (nums.size() == 1)
            return 1;

        sort(nums.begin(), nums.end());
        int ans = 1, mx = 1;
        int n = nums.size();
        for (int i = 1; i < n; i++) {
            if (nums[i] == nums[i - 1])
                continue;
            if (nums[i] == nums[i - 1] + 1) {
                mx++;
            } else {
                mx = 1;
            }
            ans = max(mx, ans);
        }
        return ans;
    }
};

双指针(4/4)

给定一个数组  nums,编写一个函数将所有  0  移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int pre = 0, cur = 0;
        while (cur < nums.size()) {
            if (nums[cur]) {
                if (pre != cur)
                    swap(nums[pre], nums[cur]);
                pre++;
            }
            cur++;
        }
    }
};

给定一个长度为  n  的整数数组  height 。有  n  条垂线,第  i  条线的两个端点是  (i, 0)  和  (i, height[i]) 。

找出其中的两条线,使得它们与  x  轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明: 你不能倾斜容器。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution {
public:
    int maxArea(vector<int>& height) {
        int l = 0, r = height.size() - 1;
        int cur = (r - l) * min(height[l], height[r]);
        int ans = cur;
        while (l < r) {
            ans = max(ans, cur);
            if (height[l] < height[r]) {
                l++;
            } else {
                r--;
            }
            cur = (r - l) * min(height[l], height[r]);
        }
        return ans;
    }
};

给你一个整数数组  nums ,判断是否存在三元组  [nums[i], nums[j], nums[k]]  满足  i != ji != k  且  j != k ,同时还满足  nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为  0  且不重复的三元组。

注意: 答案中不可以包含重复的三元组。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<vector<int>> res;
        int i = 0;
        while (i + 2 < n) {
            if (nums[i] > 0) {
                break;
            }
            if (i > 0 && nums[i] == nums[i - 1]) {
                i++;
                continue;
            }

            int l = i + 1, r = n - 1;
            while (l < r) {
                if (nums[i] + nums[l] + nums[r] < 0) {
                    l++;
                } else if (nums[i] + nums[l] + nums[r] > 0) {
                    r--;
                } else {
                    res.push_back({nums[i], nums[l], nums[r]});
                    while (l < r && nums[l] == nums[l + 1]) {
                        l++;
                    }
                    while (l < r && nums[r] == nums[r - 1]) {
                        r--;
                    }
                    l++, r--;
                }
            }
            i++;
        }
        return res;
    }
};

给定  n  个非负整数表示每个宽度为  1  的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        int lmx = 0, rmx = 0, mx = 0;
        int ans = 0;
        int l = 0, r = n - 1;
        while (l < r) {
            lmx = max(lmx, height[l]);
            rmx = max(rmx, height[r]);
            if (height[l] < height[r]) { // 低的存水上限已经定了
                ans += lmx - height[l];
                l++;
            } else {
                ans += rmx - height[r];
                r--;
            }
        }
        return ans;
    }
};

滑动窗口(2/2)

给定一个字符串  s ,请你找出其中不含有重复字符的  最长子串  的长度。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int n = s.size();
        if (!n) {
            return 0;
        }
        unordered_map<char, int> cnt;
        int l = 0, r = 1;
        int ans = 1;
        cnt[s[0]]++;
        while (r < n) {
            while (r < n && cnt[s[r]] == 0) {
                cnt[s[r]]++;
                r++;
            }
            ans = max(r - l, ans);
            while (l < r && cnt[s[r]] != 0) {
                cnt[s[l]]--;
                l++;
            }
            if (r < n) {
                cnt[s[r]]++;
                r++;
            }
        }

        return ans;
    }
};

给定两个字符串  s  和  p,找到  s  中所有  p  的  异位词  的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        if (s.size() < p.size() || s.empty() || p.empty()) {
            return {};
        }
        vector<int> ts(26, 0), tp(26, 0);
        int n = s.size(), m = p.size();
        for (int i = 0; i < m; i++) {
            ts[s[i] - 'a']++, tp[p[i] - 'a']++;
        }
        int mc = 0;
        for (int i = 0; i < 26; i++) {
            mc += tp[i] == ts[i];
        }
        int l = 0, r = m;
        vector<int> pos;
        while (r <= n) {
            if (mc == 26) {
                pos.push_back(l);
            }
            if (r == n)
                break;
            mc -= tp[s[l] - 'a'] == ts[s[l] - 'a'];
            mc -= tp[s[r] - 'a'] == ts[s[r] - 'a'];
            ts[s[l] - 'a']--, ts[s[r] - 'a']++;
            mc += tp[s[l] - 'a'] == ts[s[l] - 'a'];
            mc += tp[s[r] - 'a'] == ts[s[r] - 'a'];
            l++, r++;
        }

        return pos;
    }
};

子串(3/3)

给你一个整数数组  nums  和一个整数  k ,请你统计并返回  该数组中和为  k  的子数组的个数 。

子数组是数组中元素的连续非空序列。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> pre(n + 1, 0);
        unordered_map<int, int> mp;
        int ans = 0;
        mp[0] = 1;
        for (int i = 0; i < n; i++) {
            pre[i + 1] = pre[i] + nums[i];
            ans += mp[pre[i + 1] - k];
            mp[pre[i + 1]]++;
        }
        return ans;
    }
};

给你一个整数数组  nums,有一个大小为  k  的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的  k  个数字。滑动窗口每次只向右移动一位。

返回  滑动窗口中的最大值 。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
vector<int> maxSlidingWindow(vector<int> &nums, int k) {
  deque<int> q;
  int n = nums.size();
  for (int i = 0; i < k; i++) {
    while (!q.empty() && nums[q.back()] < nums[i]) {
      q.pop_back();
    }
    q.push_back(i);
  }
  vector<int> ans = {nums[q.front()]};
  for (int i = k; i < n; i++) {
    while (!q.empty() && q.front() <= i - k) {
      q.pop_front();
    }
    while (!q.empty() && nums[q.back()] < nums[i]) {
      q.pop_back();
    }
    q.push_back(i);
    ans.push_back(nums[q.front()]);
  }

  return ans;
}

给你一个字符串  s 、一个字符串  t 。返回  s  中涵盖  t  所有字符的最小子串。如果  s  中不存在涵盖  t  所有字符的子串,则返回空字符串  "" 。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class Solution {
public:
    string minWindow(string s, string t) {
        int n = s.size(), m = t.size();
        if (n < m) {
            return "";
        }
        vector<int> mc(128, 0), cur(128, 0);
        for (int i = 0; i < m; i++) {
            mc[t[i]]++, cur[s[i]]++;
        }

        int tot = 0;

        for (char c = 'A'; c <= 'Z'; c++) {
            if (mc[c] <= cur[c]) {
                tot++;
            }
        }
        for (char c = 'a'; c <= 'z'; c++) {
            if (mc[c] <= cur[c]) {
                tot++;
            }
        }

        int L = 0, R = 0;
        string ans = "";
        int l = 0, r = m;
        if (tot == 52) {
            if (R == 0 || r - l < R - L) {
                L = l, R = r;
            }
        }
        while (r < n) {
            while (tot != 52 && r < n) {
                tot -= cur[s[r]] >= mc[s[r]];
                cur[s[r]]++;
                tot += cur[s[r]] >= mc[s[r]];
                r++;
            }
            while (l < r && mc[s[l]] < cur[s[l]]) {
                tot -= cur[s[l]] >= mc[s[l]];
                cur[s[l]]--;
                tot += cur[s[l]] >= mc[s[l]];
                l++;
            }
            if (tot == 52) {
                if (R == 0 || r - l < R - L) {
                    L = l, R = r;
                }
            }
            tot -= cur[s[l]] >= mc[s[l]];
            cur[s[l]]--;
            tot += cur[s[l]] >= mc[s[l]];
            l++;
            while (l < r && mc[s[l]] == 0) {
                tot -= cur[s[l]] >= mc[s[l]];
                cur[s[l]]--;
                tot += cur[s[l]] >= mc[s[l]];
                l++;
            }
        }

        return s.substr(L, R - L);
    }
};

普通数组(5/5)

给你一个整数数组  nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组是数组中的一个连续部分。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int pre = 0;
        int mx = nums.front();
        for (int i : nums) {
            pre = max(pre + i, i);
            mx = max(mx, pre);
        }
        return mx;
    }
};

以数组  intervals  表示若干个区间的集合,其中单个区间为  intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回  一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end());
        vector<vector<int>> v;
        int l = -1, r = -1;
        for (auto& a : intervals) {
            if (l == -1) {
                l = a[0], r = a[1];
                continue;
            }
            if (a[0] > r) {
                v.push_back({l, r});
                l = a[0];
            }
            r = max(r, a[1]);
        }
        v.push_back({l, r});
        return v;
    }
};

给定一个整数数组  nums,将数组中的元素向右轮转  k  个位置,其中  k  是非负数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        k %= n;
        reverse(nums.begin(), nums.end());
        reverse(nums.begin(), nums.begin() + k);
        reverse(nums.begin() + k, nums.end());
    }
};

给你一个整数数组  nums,返回 数组  answer ,其中  answer[i]  等于  nums  中除  nums[i]  之外其余各元素的乘积  。

题目数据  保证  数组  nums之中任意元素的全部前缀元素和后缀的乘积都在   32 位  整数范围内。

请  不要使用除法, 且在  O(n)  时间复杂度内完成此题。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> pre(n, 1), suf(n, 1);
        pre[0] = nums[0], suf[n - 1] = nums[n - 1];
        for (int i = 1; i < n; i++) {
            pre[i] = pre[i - 1] * nums[i];
            suf[n - i - 1] = suf[n - i] * nums[n - i - 1];
        }
        vector<int> arr;
        for (int i = 0; i < n; i++) {
            if (i - 1 >= 0 && i + 1 <= n - 1)
                arr.push_back(pre[i - 1] * suf[i + 1]);
            else if (i == 0)
                arr.push_back(suf[1]);
            else
                arr.push_back(pre[n - 2]);
        }
        return arr;
    }
};

给你一个未排序的整数数组  nums ,请你找出其中没有出现的最小的正整数。

请你实现时间复杂度为  O(n)  并且只使用常数级别额外空间的解决方案。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size();
        for (int i = 0; i < n; i++) {
            if (nums[i] <= 0)
                continue;
            while (nums[i] <= n && nums[i] - 1 >= 0 &&
                   nums[nums[i] - 1] != nums[i]) {
                swap(nums[i], nums[nums[i] - 1]);
            }
        }
        for (int i = 0; i < n; i++) {
            if (nums[i] != i + 1)
                return i + 1;
        }
        return n + 1;
    }
};

矩阵(2/4)

给定一个  $m \times n$  的矩阵,如果一个元素为  0 ,则将其所在行和列的所有元素都设为  0 。请使用  原地  算法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int n = matrix.size();
        if (!n)
            return;
        int m = matrix[0].size();
        vector<bool> row(n), col(m);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (matrix[i][j] == 0) {
                    row[i] = col[j] = true;
                }
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (row[i] || col[j])
                    matrix[i][j] = 0;
            }
        }
    }
};

给你一个  m  行  n  列的矩阵  matrix ,请按照  顺时针螺旋顺序 ,返回矩阵中的所有元素。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int n = matrix.size();
        if (!n)
            return {};
        if (n == 1)
            return matrix[0];
        int m = matrix[0].size();
        if (m == 1) {
            vector<int> v;
            for (int i = 0; i < n; i++)
                v.emplace_back(matrix[i][0]);
            return v;
        }
        int x = 0, y = 0, k = 0;
        vector<pair<int, int>> dxy = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        vector<int> v = {matrix[x][y]};
        matrix[x][y] = -101;
        while (v.size() < n * m) {
            int px = x + dxy[k].first, py = y + dxy[k].second;
            if (px < 0 || px >= n || py < 0 || py >= m ||
                matrix[px][py] == -101) {
                k = (k + 1) % 4;
                px = x + dxy[k].first, py = y + dxy[k].second;
            }
            v.push_back(matrix[px][py]);
            matrix[px][py] = -101;
            x = px, y = py;
        }

        return v;
    }
};

给定一个  $n\times n$ 的二维矩阵  matrix  表示一个图像。请你将图像顺时针旋转 90 度。

你必须在  原地  旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要  使用另一个矩阵来旋转图像。

相关内容