力扣OJ(0001-100)

目录

1. 两数之和

3. 无重复字符的最长子串

7. 整数反转

8. 字符串转换整数 (atoi)

9. 回文数

11. 盛最多水的容器

12. 整数转罗马数字

14. 最长公共前缀

15. 三数之和

18. 四数之和

19. 删除链表的倒数第N个节点 (链表的离散跳跃)

20. 有效的括号

21. 合并两个有序链表

22. 括号生成

23. 合并K个升序链表

25. K 个一组翻转链表

26. 删除有序数组中的重复项

27. 移除元素

28. 找出字符串中第一个匹配项的下标

29. 两数相除

30. 串联所有单词的子串

31. 下一个排列

33. 搜索旋转排序数组

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

35. 搜索插入位置

36. 有效的数独

37. 解数独

39. 组合总和

40. 组合总和 II

41. 缺失的第一个正数

42. 接雨水

45. 跳跃游戏 II

46. 全排列

47. 全排列 II

49. 字母异位词分组

50. Pow(x, n)

51. N皇后

52. N皇后 II

53. 最大子序和

54. 螺旋矩阵

55. 跳跃游戏

56. 合并区间

58. 最后一个单词的长度

59. 螺旋矩阵 II

60. 第k个排列

61. 旋转链表

62. 不同路径

63. 不同路径 II 

64. 最小路径和

66. 加一

67. 二进制求和

69. x 的平方根

70. 爬楼梯

72. 编辑距离

73. 矩阵置零

74. 搜索二维矩阵

75. 颜色分类

76. 最小覆盖子串

77. 组合

78. 子集

79. 单词搜索

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

81. 搜索旋转排序数组 II

82. 删除排序链表中的重复元素 II

83. 删除排序链表中的重复元素

84. 柱状图中最大的矩形

85. 最大矩形

86. 分隔链表

87. 扰乱字符串

88. 合并两个有序数组

89. 格雷编码

90. 子集 II

91. 解码方法

92. 反转链表 II

93. 复原IP地址

94. 二叉树的中序遍历

95. 不同的二叉搜索树 II

96. 不同的二叉搜索树

98. 验证二叉搜索树

99. 恢复二叉搜索树

100. 相同的树


1. 两数之和

rust

3. 无重复字符的最长子串

剑指 Offer 48. 最长不含重复字符的子字符串 

7. 整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−231,  231 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。
 

示例 1:

输入:x = 123
输出:321
示例 2:

输入:x = -123
输出:-321
示例 3:

输入:x = 120
输出:21
示例 4:

输入:x = 0
输出:0
 

提示:

-231 <= x <= 231 - 1

def reverse(x: int) -> int:
    if x is 0:
        return 0
    x = ''.join(reversed(str(x)))
    while x[0] is '0':
        x = x[1:]
    return int(x)
def reverse2(x: int) -> int:
    if x < 0:
        x = -reverse(-x)
    else:
        x = reverse(x)
    return x
class Solution:
    def reverse(self, x: int) -> int:
        x=reverse2(x)
        if x<-pow(2,31) or x>=pow(2,31):
            return 0
        return x

8. 字符串转换整数 (atoi)

 剑指 Offer 67. 把字符串转换成整数

9. 回文数

题目:

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

示例 1:

输入: 121
输出: true
示例 2:

输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:

输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。
进阶:

你能不将整数转为字符串来解决这个问题吗?

代码:

class Solution {
public:
	bool isPalindrome(int x) {
		if (x < 0)return false;
		vector<int>num;
		while (x)
		{
			num.insert(num.end(), x % 10);
			x /= 10;
		}
		int len = num.size();
		for (int i = 0, j = len - 1; i < j; i++, j--)
		{
			if (num[i] - num[j])return false;
		}
		return true;
	}
};

11. 盛最多水的容器

双指针 双指针、多指针_nameofcsdn的博客-CSDN博客_双指针

12. 整数转罗马数字

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给你一个整数,将其转为罗马数字。

示例 1:

输入: num = 3
输出: "III"
示例 2:

输入: num = 4
输出: "IV"
示例 3:

输入: num = 9
输出: "IX"
示例 4:

输入: num = 58
输出: "LVIII"
解释: L = 50, V = 5, III = 3.
示例 5:

输入: num = 1994
输出: "MCMXCIV"
解释: M = 1000, CM = 900, XC = 90, IV = 4.
 

提示:

1 <= num <= 3999

class Solution {
public:
    string intToRoman(int num) {
        vector<pair<int, string>> m = {
            {1000, "M"},
            {900, "CM"},
            {500, "D"},
            {400, "CD"},
            {100, "C"},
            {90, "XC"},
            {50, "L"},
            {40, "XL"},
            {10, "X"},
            {9, "IX"},
            {5, "V"},
            {4, "IV"},
            {1, "I"}
        };
        string res = "";
        for (auto it = m.begin(); it != m.end(); it++) {
            while (num >= it->first) {
                res += it->second;
                num -= it->first;
            }
        }
        return res;
    }
};

14. 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""。

示例 1:

输入:strs = ["flower","flow","flight"]
输出:"fl"
示例 2:

输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。
 

提示:

0 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i] 仅由小写英文字母组成

def longestCommonPrefix(s1:str,s2:str) -> str:
    if s1 == '' or s2 == '':
        return ''
    if s1[0] == s2[0]:
        return s1[0]+longestCommonPrefix(s1[1:],s2[1:])
    return ''


def longestCommonPrefix2(strs: List[str]) -> str:
    if len(strs) < 2:
        return strs[0]
    strs[0] = longestCommonPrefix(strs[0], strs[-1])
    strs.pop(-1)
    return longestCommonPrefix2(strs)


class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        return longestCommonPrefix2(strs)

15. 三数之和

双指针 双指针、多指针_nameofcsdn的博客-CSDN博客_双指针

18. 四数之和

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abc 和 d 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

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

示例 1:

输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:

输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

提示:

  • 1 <= nums.length <= 200
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> res;
        int n = nums.size();
        if (n < 4) return res;
        sort(nums.begin(), nums.end());
        unordered_map<long long, vector<pair<int, int>>> mp;
        for (int i = 0; i < n - 1; i++) {
            for (int j = i + 1; j < n; j++) {
                int sum = nums[i] + nums[j];
                mp[sum].push_back({i, j});
            }
        }
        for (int i = 0; i < n - 3; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            for (int j = i + 1; j < n - 2; j++) {
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                long long sum = nums[i] + nums[j];
                long long target_sum = target - sum;
                if (mp.count(target_sum)) {
                    for (auto& p : mp[target_sum]) {
                        int k = p.first, l = p.second;
                        if (k > j) {
                            if (res.empty() || res.back() != vector<int>{nums[i], nums[j], nums[k], nums[l]}) {
                                res.push_back({nums[i], nums[j], nums[k], nums[l]});
                            }
                        }
                    }
                }
            }
        }
        return res;
    }
};

19. 删除链表的倒数第N个节点 (链表的离散跳跃)

单链表

20. 有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
 

示例 1:

输入:s = "()"
输出:true
示例 2:

输入:s = "()[]{}"
输出:true
示例 3:

输入:s = "(]"
输出:false
示例 4:

输入:s = "([)]"
输出:false
示例 5:

输入:s = "{[]}"
输出:true
 

提示:

1 <= s.length <= 104
s 仅由括号 '()[]{}' 组成

def listToMap(list:List)->dict:
    map=dict()
    for i in range(len(list)):
        map[list[i]]=i
    return map

class Solution:
    def isValid(self, s: str) -> bool:
        list=['{','}','(',')','[',']']
        map=listToMap(list)
        list=[]
        for i in range(len(s)):
            if map[s[i]]%2 == 0:
                list.append(map[s[i]])
            else:
                if len(list)==0 or list[-1]!=map[s[i]]-1:
                    return False
                else:
                    list.pop(-1)
        return len(list)==0

21. 合并两个有序链表

剑指 Offer 25. 合并两个排序的链表

22. 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:

输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:

输入:n = 1
输出:["()"]
 

提示:

1 <= n <= 8

class Solution {
public:
    vector<string>v;
    vector<string> generateParenthesis(int n) {
        string ans="";
        v.clear();
        generateParenthesis(ans,n,0,0);
        return v;
    }
    void generateParenthesis(string s,int n,int k1,int k2) {
        if(k2>k1 || k1>n)return;
        if(n==k2)v.insert(v.end(),s);
        generateParenthesis(s+'(',n,k1+1,k2);
        generateParenthesis(s+')',n,k1,k2+1);
    }
};

23. 合并K个升序链表

剑指 Offer II 078. 合并排序链表

25. K 个一组翻转链表

链表

26. 删除有序数组中的重复项

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}
 
示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
 

提示:

0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按升序排列

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        i=1
        while i < len(nums):
            if nums[i - 1] == nums[i]:
                nums.pop(i)
            else :
                i+=1
        return len(nums)

27. 移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}
 

示例 1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
 

提示:

0 <= nums.length <= 100
0 <= nums[i] <= 50
0 <= val <= 100

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        i=0
        while i < len(nums):
            if val == nums[i]:
                nums.pop(i)
            else :
                i+=1
        return len(nums)

28. 找出字符串中第一个匹配项的下标

KMP

29. 两数相除

题目:

给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。

返回被除数 dividend 除以除数 divisor 得到的商。

示例 1:

输入: dividend = 10, divisor = 3
输出: 3
示例 2:

输入: dividend = 7, divisor = -3
输出: -2
说明:

被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231,  231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。

代码:

class Solution {
public:
    int divide(int dividend, int divisor) {
        if(divisor==-1 && dividend==-2147483648 )return 2147483647;
        return dividend/divisor;
    }
};

30. 串联所有单词的子串

双指针

31. 下一个排列

字典序排列

33. 搜索旋转排序数组

二分法 二分、三分_nameofcsdn的博客-CSDN博客

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

剑指 Offer 53 - I. 在排序数组中查找数字 I 

35. 搜索插入位置

搜索else

36. 有效的数独

标准数独 经典永恒puzzle(2)数独_nameofcsdn的博客-CSDN博客_标准数独

37. 解数独

标准数独 经典永恒puzzle(2)数独_nameofcsdn的博客-CSDN博客_标准数独

39. 组合总和

DP

40. 组合总和 II

DP

41. 缺失的第一个正数

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

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

示例 1:

输入:nums = [1,2,0]
输出:3

示例 2:

输入:nums = [3,4,-1,1]
输出:2

示例 3:

输入:nums = [7,8,9,11,12]
输出:1

提示:

  • 1 <= nums.length <= 5 * 105
  • -231 <= nums[i] <= 231 - 1
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        nums.push_back(0);
        for(int i=0;i<nums.size();i++){
            int x=nums[i];
            while(x>=0 && x<nums.size() && x!=i && x!=nums[x]){
                swap(nums[i],nums[x]);
                x=nums[i];
            }
        }
        for(int i=1;i<nums.size();i++){
            if(nums[i]!=i)return i;
        }
        return nums.size();
    }
};

42. 接雨水

分治

45. 跳跃游戏 II

贪心 贪心(6)其他贪心问题_nameofcsdn的博客-CSDN博客

46. 全排列

字典序排列

47. 全排列 II

字典序排列

49. 字母异位词分组

哈希表

50. Pow(x, n)

 快速乘法、快速幂、矩阵快速幂

51. N皇后

https://blog.csdn.net/nameofcsdn/article/details/126005334

52. N皇后 II

https://blog.csdn.net/nameofcsdn/article/details/126005334

53. 最大子序和

 剑指 Offer 42. 连续子数组的最大和

54. 螺旋矩阵

 剑指 Offer 29. 顺时针打印矩阵

55. 跳跃游戏

 贪心

56. 合并区间

题目:

给出一个区间的集合,请合并所有重叠的区间。

示例 1:

输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:

输入: [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。

思路:

先排序,再按顺序依次合并即可

代码:

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>v)
    {
        sort(v.begin(), v.end());
        CloseInterval<1> opt;
        for (auto vi : v)opt.push(CloseIval<1>{ vi[0],vi[1] });
        vector<vector<int>>ans;
        for (auto ci : opt.allCi)ans.push_back(vector<int>{ci.low, ci.high});
        return ans;
    }
};

58. 最后一个单词的长度

给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。

单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。

示例 1:

输入:s = "Hello World"
输出:5
解释:最后一个单词是“World”,长度为5。

示例 2:

输入:s = "   fly me   to   the moon  "
输出:4
解释:最后一个单词是“moon”,长度为4。

示例 3:

输入:s = "luffy is still joyboy"
输出:6
解释:最后一个单词是长度为6的“joyboy”。

提示:

  • 1 <= s.length <= 104
  • s 仅有英文字母和空格 ' ' 组成
  • s 中至少存在一个单词
class Solution {
public:
    int lengthOfLastWord(string s) {
        auto v =StringOpt::stringSplit(s);
        return v.back().length();
    }
};

59. 螺旋矩阵 II

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

示例 1:

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

示例 2:

输入:n = 1
输出:[[1]]

提示:

  • 1 <= n <= 20
int dx[] = { 0,1,0,-1 };
int dy[] = { 1,0,-1,0 };

class Solution {
public:
	vector<int> spiralOrder(vector<vector<int>> matrix) {
		vector<int>ans;
		if (matrix.empty())return ans;
		int k = 0, len = matrix.size() * matrix[0].size();
		int x = 0, y = 0;
		while (len--)
		{
			if (x < 0 || x >= matrix.size() || y < 0 || y >= matrix[0].size() || matrix[x][y] == -1234567)
			{
				x -= dx[k], y -= dy[k];
				k++, k %= 4;
				x += dx[k], y += dy[k];
			}
			ans.push_back(matrix[x][y]);
			matrix[x][y] = -1234567;
			x += dx[k], y += dy[k];
		}
		return ans;
	}
	vector<vector<int>> generateMatrix(int n) {
		vector<vector<int>> matrix(n);
		for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)matrix[i].push_back(i * n + j);
		vector<int> v = spiralOrder(matrix);
		for (int i = 0; i < n * n; i++)matrix[v[i] / n][v[i] % n] = i+1;
		return matrix;
	}
};

60. 第k个排列

排列组合问题

61. 旋转链表

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

示例 1:

输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]

示例 2:

输入:head = [0,1,2], k = 4
输出:[2,0,1]

提示:

  • 链表中节点的数目在范围 [0, 500] 内
  • -100 <= Node.val <= 100
  • 0 <= k <= 2 * 109
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(head==nullptr)return head;
        int len = LinkGetLength(head);
        if(k%len==0)return head;
        auto p = LinkList::linkSplit(head,len - k%len);
        LinkList::getTail(p)->next=head;
        return p;
    }
};

62. 不同路径

全排列

63. 不同路径 II 

DP 高维DP_nameofcsdn的博客-CSDN博客

64. 最小路径和

DP 高维DP_nameofcsdn的博客-CSDN博客

66. 加一

题目:

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。
示例 2:

输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。

代码:

class Solution {
public:
	vector<int> plusOne(vector<int>& digits) {
		int key = 1;
		for (auto it = digits.end() - 1;key && it >= digits.begin(); it--)
		{
			*it += key, key--;
			key += (*it) / 10, *it %= 10;
		}
		if (key == 1)digits.insert(digits.begin(), 1);
		return digits;
	}
};

67. 二进制求和

 剑指 Offer II 002. 二进制加法

69. x 的平方根

题目:

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 1:

输入: 4
输出: 2
示例 2:

输入: 8
输出: 2
说明: 8 的平方根是 2.82842..., 
     由于返回类型是整数,小数部分将被舍去。

代码:

class Solution {
public:
    int mySqrt(int x) {
        return int(sqrt(x));
    }
};

70. 爬楼梯

完全背包

72. 编辑距离

高维dp

73. 矩阵置零

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

示例 1:

输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]

示例 2:

输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]

提示:

  • m == matrix.length
  • n == matrix[0].length
  • 1 <= m, n <= 200
  • -231 <= matrix[i][j] <= 231 - 1

进阶:

  • 一个直观的解决方案是使用  O(mn) 的额外空间,但这并不是一个好的解决方案。
  • 一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
  • 你能想出一个仅使用常量空间的解决方案吗?
class Solution {
public:
	void setZeroes(vector<vector<int>>& matrix) {
		map<int, int>mr, mc;
		for (int i = 0; i < matrix.size(); i++) {
			for (int j = 0; j < matrix[0].size(); j++) {
				if (matrix[i][j] == 0)mr[i] = mc[j] = 1;
			}
		}
		for (int i = 0; i < matrix.size(); i++) {
			for (int j = 0; j < matrix[0].size(); j++) {
				if (mr[i] || mc[j]) matrix[i][j] = 0;
			}
		}
	}
};

74. 搜索二维矩阵

 二分、三分

75. 颜色分类

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

必须在不使用库内置的 sort 函数的情况下解决这个问题。

示例 1:

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
示例 2:

输入:nums = [2,0,1]
输出:[0,1,2]
 

提示:

n == nums.length
1 <= n <= 300
nums[i] 为 0、1 或 2
 

进阶:

你能想出一个仅使用常数空间的一趟扫描算法吗?

class Solution {
public:
	void sortColors(vector<int>& nums) {
		for (int i = 0, j = nums.size() - 1, k = 0; i <= j; i++) {
			if (nums[i] == 0 && i>k)nums[k++] ^= nums[i--] ^= nums[k] ^= nums[i];
			if (nums[i] == 2 && i<j)nums[j--] ^= nums[i--] ^= nums[j] ^= nums[i];
		}
	}
};

76. 最小覆盖子串

 双指针

77. 组合

排列组合

78. 子集

排列组合问题

79. 单词搜索

DFS

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

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

示例 1:

输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]
解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。 不需要考虑数组中超出新长度后面的元素。

示例 2:

输入:nums = [0,0,1,1,1,1,2,3,3]
输出:7, nums = [0,0,1,1,2,3,3]
解释:函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。 不需要考虑数组中超出新长度后面的元素。

提示:

  • 1 <= nums.length <= 3 * 104
  • -104 <= nums[i] <= 104
  • nums 已按升序排列
class Solution {
public:
	int removeDuplicates(vector<int>& nums) {
		for (int i = 2; i < nums.size(); i++) {
			if (nums[i] == nums[i - 2])nums.erase(nums.begin() + i--);
		}
		return nums.size();
	}
};

81. 搜索旋转排序数组 II

题目:

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。

编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false

示例 1:

输入: nums = [2,5,6,0,0,1,2], target = 0
输出: true

示例 2:

输入: nums = [2,5,6,0,0,1,2], target = 3
输出: false

分析:

本题没有复杂度优于O(n)的算法。

代码:

class Solution {
public:
	bool search(vector<int>& nums, int target) {
		for (auto it = nums.begin(); it != nums.end(); it++)if (*it == target)return true;
		return false;
	}
};

82. 删除排序链表中的重复元素 II

链表

83. 删除排序链表中的重复元素

链表

84. 柱状图中最大的矩形

单调栈

85. 最大矩形

单调栈

86. 分隔链表

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

示例 1:

输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]

示例 2:

输入:head = [2,1], x = 2
输出:[1,2]

提示:

  • 链表中节点的数目在范围 [0, 200] 内
  • -100 <= Node.val <= 100
  • -200 <= x <= 200
class Solution {
public:
	ListNode* partition(ListNode* head, int x) {
		auto p = head;
		vector<int>v;
		while (p) {
			if (p->val < x)v.push_back(p->val);
			p = p->next;
		}
		p = head;
		while (p) {
			if (p->val >= x)v.push_back(p->val);
			p = p->next;
		}
        return InitLinkList(v);
	}
};

87. 扰乱字符串

高维DP

88. 合并两个有序数组

双指针

89. 格雷编码

编码技术大全

90. 子集 II

排列组合

91. 解码方法

 加解密

92. 反转链表 II

链表

93. 复原IP地址

给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。

有效的 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成),整数之间用 '.' 分隔。

示例:

输入: "25525511135"
输出: ["255.255.11.135", "255.255.111.35"]

class Solution {
public:
    vector<string> restoreIpAddresses(string s,int k) {
        vector<string>ans;
        if(s.length()==0)return ans;
        if(k>1)for(int i=0;i<3 && i<s.length()-1;i++)
        {
            string s1=s.substr(0,i+1),s2=s.substr(i+1,s.length()-i-1);
            int x=atoi(s1.c_str());
            if(x>255 || s[0]=='0' && s1.length()>1 || s1.length()>3)continue;
            vector<string>tmp=restoreIpAddresses(s2,k-1);
            for(int j=0;j<tmp.size();j++)
            {
                string s3=tmp[j];
                ans.push_back(s1+"."+s3);
            }
        }
        else
        {
            int x=atoi(s.c_str());
            if(x>255 || s[0]=='0' && s.length()>1 || s.length()>3);
            else ans.push_back(s);
        }
        return ans;
    }
    vector<string> restoreIpAddresses(string s) {
        return restoreIpAddresses(s,4);
    }
};

94. 二叉树的中序遍历

 二叉树

95. 不同的二叉搜索树 II

二叉搜索树(BST)

96. 不同的二叉搜索树

二叉搜索树(BST)

98. 验证二叉搜索树

二叉搜索树(BST)

99. 恢复二叉搜索树

二叉搜索树

100. 相同的树

二叉树DFS

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值