文章目录

  • 目标
  • leetcode
    • 1.两数之和
    • 2.两数相加(同时遍历2个链表)
    • 3.最长不重复子字符串
    • 4.寻找两个正序数组的中位数
    • 5.最长回文字串(双指针从中间向两边遍历的写法)
    • 6. N字形变换(flag=1/-1实现转圈遍历)
    • 7.整数转字符串(取模和除法操作)
    • 8. 字符串转整数--
    • 9. 回文数--
    • 10. 正则表达式(todo)
    • 11. 盛最多水的容器(最差的动起来可能更差可能更好,但不动一定很差)
    • 12. 整数转罗马数字(贪心hash表)
    • 13. 罗马转整数(普通hash表&特殊hash表,先试走2步看特殊,再走一步看普通)
    • 14. 最长公共前缀---
    • 15. 三数之和-最接近三数之和-四数之和(组合拳:排序+定一移二(双指针))
    • 17. 电话号码组合(递归回溯的框架来解)
      • Excel表列名称_字母转EXCEL列(10进制转26进制)
    • 19. 删除链表的倒数第 N 个结点
    • 20. 有效的括号(辅助栈)
    • 21. 合并两个有序链表
    • 22. 括号生成(递归)
    • 23. 合并K个升序链表(todo)
    • 24. 两两交换链表中的节点
    • 25. K 个一组翻转链表(todo)
    • 26. 删除有序数组中的重复项(双指针的有趣解释)
    • 27. 移除元素(空间优化)
    • 28.找出字符串中第一个匹配项的下标(KMP 算法todo)
    • 29 两数相除---
    • 30. 串联所有单词的子串todo
    • 31. 下一个排列
    • 32. 最长有效括号todo
    • 33. 搜索旋转排序数组
    • 34. 在排序数组中查找元素的第一个和最后一个位置
    • 35.搜索插入位置---
    • 36.有效的数独
    • 37. 解数独todo
    • 38. 外观数列
    • 39. 组合总和
    • 40. 组合总和 II
    • 41. 缺失的第一个正数todo
    • 42. 接雨水
    • 43. 字符串相乘---
    • 44. 通配符匹配 todo
    • 45. 跳跃游戏I,II
    • 46. 全排列I,II
    • 48. 旋转图像
    • 49. 字母异位分词
    • 50. pow(x,n)
    • 51. N皇后‖
    • 53. 最大子数组和
    • 54. 螺旋矩阵1..2
    • 56. 合并区间
    • 57. 插入区间
    • 58. 最后一个单词的长度x
    • 60. 排列序列todo
    • 61. 旋转链表
    • 62. 不同路径I,II
    • 64. 最小路径和
    • 65. 有效数字todo
    • 66. 加一
    • 67. 二进制求和
    • 68. 文本左右对齐todo
    • 69. x 的平方根
    • 71. 简化路径
    • 72. 编辑距离todo
    • 73. 矩阵置零
    • 75. 颜色分类
    • 76. 最小覆盖子串todo
    • 78. 子集(做过)
    • 79. 单词搜索
    • 84. 柱状图中最大的矩形 todo
    • 85. 最大矩形 todo
    • 93. 复原 IP 地址
    • 94. 二叉树的中序遍历
    • 101. 对称二叉树
    • 102. 二叉树的层序遍历 (队列)
    • 103. 二叉树的锯齿形层序遍历(双端队列)
    • 104. 二叉树的最大深度
    • 105. 从前序与中序遍历序列构造二叉树todo
    • 106.从中序与后序遍历序列构造二叉树todo
    • 107.二叉树的层序遍历 II(正向输出然后再逆转)
    • 108. 将有序数组转换为二叉搜索树(递归构造平衡二叉树搜索树)
    • 109. 有序链表转换二叉搜索树
    • 115. 不同的子序列(todo)
    • 116. 填充每个节点的下一个右侧节点指针
    • 118. 杨辉三角
    • 119. 杨辉三角 II
    • 128. 最长连续序列(在hash表中不断枚举匹配x+1,x+2...x+y,判断x-1在hash表中是否存在就能避免重复的枚举)
    • 134. 加油站
    • 136. 只出现一次的数字(异或运算的经典案例)
    • 137. 只出现一次的数字 II(delete)
    • 138. 复制带随机指针的链表
    • 139. 单词拆分
    • 141. 环形链表(龟兔赛跑算法-空间优化)
    • 142. 环形链表 II
    • 143. 重排链表
    • 144. 二叉树的前序遍历/后序遍历
    • 146. LRU 缓存
    • 147. 对链表进行插入排序todo
    • 148. 排序链表
    • 150. 逆波兰表达式求值
    • 151. 反转字符串中的单词(要求O(1))
    • 169. 多数元素(投票算法)
    • 229. 多数元素 II
    • 224. 基本计算器
    • 227. 基本计算器 II
    • 232. 用栈实现队列
    • 237. 删除链表中的节点
    • 257. 二叉树的所有路径
    • 258. 各位相加(数学问题)
    • 260. 只出现一次的数字 III(位运算-跳过)
    • 263. 丑数
    • 264. 丑数 II
    • 268. 丢失的数字(原地哈希将空间复杂度降低为O(1)很6)
    • 274. H 指数(H 指数换一种理解就是:统计降序排列的数组中下标比下标值大的个数)
    • 275. H 指数 II
    • 279. 完全平方数
    • 283. 移动零(双指针)
    • 287. 寻找重复数
    • 290. 单词规律(将map的put性质发挥到了极致:如果key不存在,插入成功,返回null;如果key存在,返回之前对应的value)
    • 287. 寻找重复数
    • 289. 生命游戏todo
    • 292. Nim 游戏
    • 299. 猜数字游戏
    • 300. 最长递增子序列
  • 附加

目标

算法60分的标准:夯实基础

  • 把leedcode200道题默写3遍
  • 把算法框架(每框架最经典的3个题)默写3遍

算法80分的标准:扩展提升

  • Lfu,lru,跳表,排序,红黑树,背包问题,外企算法50题默写3遍
  • Leedcode200-300的题目默写3遍
  • 把算法框架(每框架10个题)默写3遍

leetcode

1.两数之和

class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();for (int i = 0; i < nums.length; ++i) {if (hashtable.containsKey(target - nums[i])) {return new int[]{hashtable.get(target - nums[i]), i};}hashtable.put(nums[i], i);}return new int[0];}
}
func twoSum(nums []int, target int) []int {hashmap := make(map[int]int)for i,v := range nums{if index,ok := hashmap[target-v]; ok{return []int{i,index}}hashmap[v]=i}return nil
}

2.两数相加(同时遍历2个链表)

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode(int x) { val = x; }* }*/
class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {// 学习点ListNode pre = new ListNode(0);ListNode cur = pre;int carry = 0;// 学习点:同时遍历2个链表while(l1 != null || l2 != null) {// 学习点int x = l1 == null ? 0 : l1.val;int y = l2 == null ? 0 : l2.val;int sum = x + y + carry;// 学习点carry = sum / 10;sum = sum % 10;cur.next = new ListNode(sum);cur = cur.next;if(l1 != null)l1 = l1.next;if(l2 != null)l2 = l2.next;}if(carry == 1) {cur.next = new ListNode(carry);}return pre.next;}
}
/*** Definition for singly-linked list.* type ListNode struct {*     Val int*     Next *ListNode* }*/
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {flag := 0 l3 := &ListNode{Val:0}head := l3for l1 != nil || l2 != nil {a1,a2 := 0,0if l1 != nil{a1 = l1.Vall1 = l1.Next}if l2 != nil{a2 = l2.Vall2 = l2.Next}temp := a1+a2+flagl3.Next = &ListNode{Val:temp%10}l3 = l3.Nextflag = temp/10}if flag > 0{l3.Next = &ListNode{Val:flag}}return head.Next
}

3.最长不重复子字符串

快指针先往前试探(看看会不会重复:重复就移动左指针,并计数)

rk,ans = -1,0
for i:=0;i<n;i++{delete(map,arr[i])//未出现过重复的for r < n && map[arr[i+1]] == 0 { //等价于 map[arr[i]] = 1  map[arr[i+1]]++rk++}
}

4.寻找两个正序数组的中位数

(困难题:能说出思路就行)

//题目是求中位数,其实就是求第 k 小数,比如下面2个有序数组合并后长度为14,其中位数就是第7小的数(14/2=7)
https://leetcode.cn/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/// 如果下图的1数组1349只有9,那么1数组去第三小的数不是4而是用1代替,取第三小的数,但如果数组只有第1小或者第二小就用第1小或者第二小代替
int i = start1 + Math.min(len1, k / 2) - 1;



5.最长回文字串(双指针从中间向两边遍历的写法)

public String longestPalindrome(String s) {if (s == null || s.length() < 1) return "";int start = 0, end = 0;for (int i = 0; i < s.length(); i++) {int len1 = expandAroundCenter(s, i, i);int len2 = expandAroundCenter(s, i, i + 1);int len = Math.max(len1, len2);if (len > end - start) {start = i - (len - 1) / 2;end = i + len / 2;}}return s.substring(start, end + 1);
}// 学习点
private int expandAroundCenter(String s, int left, int right) {int L = left, R = right;while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {L--;R++;}return R - L - 1;
}作者:windliang
链接:https://leetcode.cn/problems/longest-palindromic-substring/solutions/9001/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-bao-gu/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
expandAroundCenter(i,i)
expandAroundCenter(i,i+1)
func expandAroundCenter(L,R){for L >= 0 && R <= len(s) && s[L]=s[R] {    L++R++
}}

6. N字形变换(flag=1/-1实现转圈遍历)

class Solution {public String convert(String s, int numRows) {if(numRows < 2) return s;List<StringBuilder> rows = new ArrayList<StringBuilder>();for(int i = 0; i < numRows; i++) rows.add(new StringBuilder());int i = 0, flag = -1;for(char c : s.toCharArray()) {rows.get(i).append(c);// 学习点 : if(i == 0 || i == numRows -1) flag = - flag;i += flag;}StringBuilder res = new StringBuilder();for(StringBuilder row : rows) res.append(row);return res.toString();}
}作者:Krahets
链接:https://leetcode.cn/problems/zigzag-conversion/solutions/21610/zzi-xing-bian-huan-by-jyd/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
var flag = 1if j==0 || j = numRows-1 {flag = -flagj = j+flag
}

7.整数转字符串(取模和除法操作)

//取模和除法操作
//一旦涉及整数的运算,我们需要注意溢出。本题可能产生溢出的步骤在于推入、乘以 1010 操作和累加操作都可能造成溢出。对于溢出的处理方式通常可以转换为 INT_MAX 的逆操作。比如判断某数乘以 1010 是否会溢出,那么就把该数和 INT_MAX 除以 1010 进行比较。
while(num != 0)
num%10
num/10

8. 字符串转整数–

9. 回文数–

10. 正则表达式(todo)

1. 考虑*可能为0,所以可以在遍历的时候往后多看一步
2. 从左往右分析可能较复杂,那么可以从右往左分析
// todo

11. 盛最多水的容器(最差的动起来可能更差可能更好,但不动一定很差)

果然,第一次做题很难想到双指针。就像我昨天说的,有些题目思路到底怎么来的?凭什么就是这样,怎么想到的。原来是见过了才知道。解题思路解题思路,解过了才有思路。以后别再跟我扯什么解题模板,多解题才有模板。双指针模板我也知道,但这道题就是想不到用双指针。以后就知道了,所以啊,还是要多解题,多解题才有解题思路。


感觉这个移动有点博弈论的味了,每次都移动自己最差的一边,虽然可能变得更差,但是总比不动(或者减小)强,动最差的部分可能找到更好的结果,但是动另一边总会更差或者不变,兄弟们,这不是题,这是人生,逃离舒适圈!!(这解释我觉得无敌了,哈哈哈)

让快指针多往后看几步

12. 整数转罗马数字(贪心hash表)

贪心hash表,从最大的开始匹配

class Solution:def intToRoman(self, num: int) -> str:# 使用哈希表,按照从大到小顺序排列hashmap = {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'}res = ''for key in hashmap:if num // key != 0:count = num // key  # 比如输入4000,count 为 4res += hashmap[key] * count num %= keyreturn res作者:腐烂的橘子
链接:https://leetcode.cn/problems/integer-to-roman/solutions/87905/tan-xin-ha-xi-biao-tu-jie-by-ml-zimingmeng/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

13. 罗马转整数(普通hash表&特殊hash表,先试走2步看特殊,再走一步看普通)


class Solution {public static int romanToInt(String s) {Map<Character,Integer> map = new HashMap<>();map.put('I',1);map.put('V',5);map.put('X',10);map.put('L',50);map.put('C',100);map.put('D',500);map.put('M',1000);
//        I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
//        X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
//        C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。Map<String,Integer> map1 = new HashMap<>();map1.put("IV",4);map1.put("IX",9);map1.put("XL",40);map1.put("XC",90);map1.put("CD",400);map1.put("CM",900);int sum = 0;for (int i = 0; i < s.length(); i++) {if (i+2<=s.length()&&map1.get(s.substring(i,i+2))!=null){sum+=map1.get(s.substring(i,i+2));i++;}else {sum+=map.get(s.charAt(i));}}return sum;}
}作者:黄吉华
链接:https://leetcode.cn/problems/roman-to-integer/solutions/2175843/java-ha-xi-biao-luo-ji-jian-dan-yi-dong-so3qw/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

14. 最长公共前缀—

15. 三数之和-最接近三数之和-四数之和(组合拳:排序+定一移二(双指针))

排序+定一移二(双指针)
三数之和

class Solution {public static List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> ans = new ArrayList();int len = nums.length;if(nums == null || len < 3) return ans;Arrays.sort(nums); // 排序for (int i = 0; i < len ; i++) {if(nums[i] > 0) break; // 如果当前数字大于0,则三数之和一定大于0,所以结束循环if(i > 0 && nums[i] == nums[i-1]) continue; // 去重int L = i+1;int R = len-1;while(L < R){int sum = nums[i] + nums[L] + nums[R];if(sum == 0){ans.add(Arrays.asList(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--;}else if (sum < 0) L++;else if (sum > 0) R--;}}        return ans;}
}作者:画手大鹏
链接:https://leetcode.cn/problems/3sum/solutions/12307/hua-jie-suan-fa-15-san-shu-zhi-he-by-guanpengchn/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最接近三数之和

17. 电话号码组合(递归回溯的框架来解)

隐形的二叉树来分析

Excel表列名称_字母转EXCEL列(10进制转26进制)
class Solution {public String convertToTitle(int columnNumber) {return columnNumber == 0 ? "" : convertToTitle(--columnNumber / 26) + (char)('A' + (columnNumber % 26));}
}

19. 删除链表的倒数第 N 个结点

问题转化:快指针先往前走array.length-N步
快指针往前多走几步,去探路,情况ok,慢指针再跟上

20. 有效的括号(辅助栈)

辅助栈—遇到左括号入栈,遇到右括号出栈

class Solution {private static final Map<Character,Character> map = new HashMap<Character,Character>(){{put('{','}'); put('[',']'); put('(',')'); put('?','?');}};public boolean isValid(String s) {if(s.length() > 0 && !map.containsKey(s.charAt(0))) return false;LinkedList<Character> stack = new LinkedList<Character>() {{ add('?'); }};for(Character c : s.toCharArray()){if(map.containsKey(c)) stack.addLast(c);else if(map.get(stack.removeLast()) != c) return false;}return stack.size() == 1;}
}作者:Krahets
链接:https://leetcode.cn/problems/valid-parentheses/solutions/9185/valid-parentheses-fu-zhu-zhan-fa-by-jin407891080/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

21. 合并两个有序链表

22. 括号生成(递归)

剩余左括号总数要小于等于右括号。 递归把所有符合要求的加上去就行了:

class Solution {List<String> res = new ArrayList<>();public List<String> generateParenthesis(int n) {if(n <= 0){return res;}getParenthesis("",n,n);return res;}private void getParenthesis(String str,int left, int right) {if(left == 0 && right == 0 ){res.add(str);return;}if(left == right){//剩余左右括号数相等,下一个只能用左括号getParenthesis(str+"(",left-1,right);}else if(left < right){//剩余左括号小于右括号,下一个可以用左括号也可以用右括号if(left > 0){getParenthesis(str+"(",left-1,right);}getParenthesis(str+")",left,right-1);}}}

23. 合并K个升序链表(todo)

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

while(temp.next != null && temp.next.next != null) {

25. K 个一组翻转链表(todo)

26. 删除有序数组中的重复项(双指针的有趣解释)

常用于查找或者删除相同元素、判定链表中是否含有环、寻找链表的中点等相关问题的求解
我们常用的二分查找也是利用了这钟算法思想,常见的还有两数之和、反转数组等问题的求解

int removeDuplicates(std::vector<int>& nums) {int length = nums.size();if (length == 0) return 0;int slow = 0, fast = 1;while (fast < length) {if (nums[fast] != nums[slow]) {nums[++slow] = nums[fast];}fast++;}return slow + 1;
}

题目:外面有宝,赶紧捡回来按序放好,不能重样哟 有点像小夫妻俩,老公q在外面淘宝,找到后运回来,找到一个新的宝,老婆p在家里就给挖个新坑放好,最后外面没宝了,就结束咯

中间对话

老公:老婆,这个家里有没?(if) 老婆:有了。(nums[p] == nums[q])你再找找(q++)

老公:老婆,这个家里有没?(if) 老婆:有了。(nums[p] == nums[q])你再找找(q++)

老公:老婆,这个家里有没?(if) 老婆:这个没有,拿回来吧 (nums[p] != nums[q]) 放好了,我到下一个位置等你(p++) 你再继续找吧(q++)

貌似双指针都可以这么理解

27. 移除元素(空间优化)

原地移除指定的值

双指针—图解
https://leetcode.cn/problems/remove-element/solution/hua-jie-suan-fa-27-yi-chu-yuan-su-by-guanpengchn/

class Solution {public int removeElement(int[] nums, int val) {int ans = 0;for(int num: nums) {if(num != val) {nums[ans] = num;ans++;}}return ans;}
}作者:画手大鹏
链接:https://leetcode.cn/problems/remove-element/solutions/10388/hua-jie-suan-fa-27-yi-chu-yuan-su-by-guanpengchn/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

28.找出字符串中第一个匹配项的下标(KMP 算法todo)

暴力匹配

我们可以让字符串 needle与字符串 haystack的所有长度为 m 的子串均匹配一次。

为了减少不必要的匹配,我们每次匹配失败即立刻停止当前子串的匹配,对下一个子串继续匹配。如果当前子串匹配成功,我们返回当前子串的开始位置即可。如果所有子串都匹配失败,则返回 −1。

// 简化代码的写法也很巧妙
class Solution {public int strStr(String haystack, String needle) {int n = haystack.length(), m = needle.length();for (int i = 0; i + m <= n; i++) {boolean flag = true;for (int j = 0; j < m; j++) {if (haystack.charAt(i + j) != needle.charAt(j)) {flag = false;break;}}if (flag) {return i;}}return -1;}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/solutions/732236/shi-xian-strstr-by-leetcode-solution-ds6y/
来源:力扣(LeetCode)

29 两数相除—

转乘法:官方题解

朴素的想法,没有位运算,没有移位操作

30. 串联所有单词的子串todo

31. 下一个排列

思路:逆序—(交换)—正序操作
https://leetcode.cn/problems/next-permutation/solution/xia-yi-ge-pai-lie-yi-kan-jiu-dong-by-ych-983q/

从最后一个数开始排,依次往前找有比它小的没有,有就交换位置,结束循环,找了一圈都没有,从倒数第二个数重复上述操作。直到第一个数都还没有进行一次操作,就反转整个数就是答案

123--->132
132--->213
231--->321--->123
class Solution {public:void nextPermutation(vector<int>& nums) {int cur=nums.size()-2;while(cur>=0&&nums[cur]>=nums[cur+1])//前面大于后面的{cur--;}if(cur<0)//已经是最大数组了sort(nums.begin(),nums.end());else//表示找到了降序的一个位置{int pos=nums.size()-1;while(nums[pos]<=nums[cur]){pos--;}swap(nums[cur],nums[pos]);reverse(nums.begin()+cur+1,nums.end());}}
};

32. 最长有效括号todo

33. 搜索旋转排序数组

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

35.搜索插入位置—

36.有效的数独

用hash表

class Solution {public boolean isValidSudoku(char[][] board) {int[][] rows = new int[9][9];int[][] columns = new int[9][9];int[][][] subboxes = new int[3][3][9];for (int i = 0; i < 9; i++) {for (int j = 0; j < 9; j++) {char c = board[i][j];if (c != '.') {int index = c - '0' - 1;rows[i][index]++;columns[j][index]++;subboxes[i / 3][j / 3][index]++;if (rows[i][index] > 1 || columns[j][index] > 1 || subboxes[i / 3][j / 3][index] > 1) {return false;}}}}return true;}
}作者:LeetCode-Solution
链接:https://leetcode.cn/problems/valid-sudoku/solution/you-xiao-de-shu-du-by-leetcode-solution-50m6/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

37. 解数独todo

38. 外观数列

【【LeetCode 每日一题】38. 外观数列 | 手写图解版思路 + 代码讲解-哔哩哔哩】 https://b23.tv/ArN8pXT

i
111221
ji
111221j可得31i
111221ji
111221j可得22【3122】
string dg(){if n ==1 return "1"
string s = dg(n - 1 )
string ansfor(双指针)
}

39. 组合总和




40. 组合总和 II

排序2大好处:可剪枝,可去重arr[i]==arr[i-1]----直接跳过本次操作
【40-组合总和Ⅱ-哔哩哔哩】 https://b23.tv/aVWOyiO

41. 缺失的第一个正数todo

42. 接雨水

https://leetcode.cn/problems/trapping-rain-water/solution/by-lfool-5see/
这个题目也差不多,我们需要维护一个高度 h,表示能使水不流走的最大高度!!

在使用双指针收缩区间的时候,不断的更新该高度 h

public int trap(int[] height) {int h = 0, ans = 0;int l = 0, r = height.length - 1;while (l <= r) {if (height[l] < height[r]) {h = Math.max(h, height[l]);ans += h - height[l];l++;} else {h = Math.max(h, height[r]);ans += h - height[r];r--;}}return ans;
}

43. 字符串相乘—

44. 通配符匹配 todo

45. 跳跃游戏I,II

https://leetcode.cn/problems/jump-game-ii/solution/tiao-yue-you-xi-ii-by-leetcode-solution/

46. 全排列I,II

排序,用下面这个判断条件就能进行过滤

if (i > 0 && nums[i] == nums[i - 1] && !vis[i - 1]) {continue;
}

48. 旋转图像


class Solution {public:void rotate(vector<vector<int>>& matrix) {//先沿斜对角线翻转int n = matrix.size();for(int i = 0; i < n; i++)for(int j = 0; j < i; j++)swap(matrix[i][j],matrix[j][i]);//再沿垂直竖线翻转for(int i = 0;i < n; i++)for(int j = 0, k = n - 1; j < k ; j++, k--) //类似于双指针,由两端向中心靠齐swap(matrix[i][j],matrix[i][k]);        }
};作者:lin-shen-shi-jian-lu-k
链接:https://leetcode.cn/problems/rotate-image/solution/48-xuan-zhuan-tu-xiang-chao-jian-ji-yi-d-nuau/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

49. 字母异位分词

https://leetcode.cn/problems/group-anagrams/solution/zi-mu-yi-wei-ci-fen-zu-by-leetcode-solut-gyoc/

50. pow(x,n)

二分快速幂方法
https://leetcode.cn/problems/powx-n/solution/powx-n-by-leetcode-solution/

51. N皇后‖

53. 最大子数组和

54. 螺旋矩阵1…2

https://leetcode.cn/problems/spiral-matrix-ii/solution/spiral-matrix-ii-mo-ni-fa-she-ding-bian-jie-qing-x/

56. 合并区间

class Solution {public:vector<vector<int>> merge(vector<vector<int>>& intervals) {vector<vector<int>> ans;sort(intervals.begin(), intervals.end());int start = intervals[0][0], end = intervals[0][1];for (int i = 1; i < intervals.size(); i++) {if (intervals[i][0] > end) {ans.push_back({start, end});start = intervals[i][0];end = intervals[i][1];} else {end = max(end, intervals[i][1]);}}ans.push_back({start, end});return ans;}
};

57. 插入区间

可参考视频讲解链接:https://www.bilibili.com/video/BV1VZ4y1C7po?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=d482cc951729db66c853a9d4fef3b529

class Solution {public:vector<vector<int>> insert(vector<vector<int>>& a, vector<int>& b) {vector<vector<int>> ans;int n = a.size(), i = 0;// 添加左侧不重叠区间while (i < n && a[i][1] < b[0]) {ans.push_back(a[i++]);}// 合并中间重叠区间if (i < n) {b[0] = min(a[i][0], b[0]);while (i < n && a[i][0] <= b[1]) {b[1] = max(a[i++][1], b[1]);}}ans.push_back(b);// 添加右侧不重叠区间while (i < n) {ans.push_back(a[i++]);}return ans;}
};

58. 最后一个单词的长度x

60. 排列序列todo

61. 旋转链表

闭合为环,然后砍断(官方题解就行)

62. 不同路径I,II

https://leetcode.cn/problems/unique-paths/solution/san-chong-shi-xian-xiang-xi-tu-jie-62-bu-4jz1/

64. 最小路径和

65. 有效数字todo

66. 加一

思路都一样,编码方式却又不同—该题比较有启发性

分两种情况处理每一位上的数加一后的结果:加到10,没加到10
没加到10直接返回
加到10,继续进行下一位的加一操作,表示进1
https://leetcode.cn/problems/plus-one/solution/by-leer-e-xsy9/

67. 二进制求和

官方题解中的位运算可以拓展学习
https://leetcode.cn/problems/add-binary/solution/er-jin-zhi-qiu-he-by-leetcode-solution/

class Solution {public String addBinary(String a, String b) {int i = a.length() - 1;int j = b.length() - 1;int carry = 0;StringBuilder builder = new StringBuilder();//循环相加两个字符串相同长度的低位数部分while (i >= 0 && j >= 0) {int sum = carry;sum += a.charAt(i--) - '0';sum += b.charAt(j--) - '0';carry = sum / 2;builder.append(sum % 2);}// 如果 a 还没遍历完成(a串比b串长),则继续遍历添加 a 的剩余部分while (i >= 0) {int sum = carry + a.charAt(i--) - '0';carry = sum / 2;builder.append(sum % 2);}// 如果 b 还没遍历完成(b串比a串长),则继续遍历添加 b 的剩余部分while (j >= 0) {int sum = carry + b.charAt(j--) - '0';carry = sum / 2;builder.append(sum % 2);}//如果 carry 不等于0 还有个进位数没加进去,需要补充if (carry == 1) {builder.append(carry);}//反转字符串获得正常结果return builder.reverse().toString();}

68. 文本左右对齐todo

69. x 的平方根

二分查找
https://leetcode.cn/problems/sqrtx/solution/x-de-ping-fang-gen-by-leetcode-solution/

71. 简化路径

72. 编辑距离todo

73. 矩阵置零

75. 颜色分类

https://leetcode.cn/problems/sort-colors/solution/yan-se-fen-lei-by-leetcode-solution/
看完所有的数
循环不变量

76. 最小覆盖子串todo

78. 子集(做过)

79. 单词搜索

https://leetcode.cn/problems/word-search/solution/dan-ci-sou-suo-by-leetcode-solution/

84. 柱状图中最大的矩形 todo

85. 最大矩形 todo

93. 复原 IP 地址

94. 二叉树的中序遍历

101. 对称二叉树

/*** Definition for a binary tree node.* type TreeNode struct {*     Val int*     Left *TreeNode*     Right *TreeNode* }*/
func isSymmetric(root *TreeNode) bool {return check(root,root)
}func check(l *TreeNode ,r *TreeNode) bool{if l == nil && r == nil {return true}if (l == nil && r!=nil ) || ( l != nil && r == nil ) {return false} return l.Val == r.Val && check(l.Left,r.Right) && check(l.Right,r.Left)
}

102. 二叉树的层序遍历 (队列)

103. 二叉树的锯齿形层序遍历(双端队列)

如果从左至右,我们每次将被遍历到的元素插入至双端队列的末尾。

如果从右至左,我们每次将被遍历到的元素插入至双端队列的头部。

104. 二叉树的最大深度

遇到null返回0,否则返回max(递归函数())+1

105. 从前序与中序遍历序列构造二叉树todo

class Solution {private Map<Integer, Integer> indexMap;public TreeNode myBuildTree(int[] preorder, int[] inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {if (preorder_left > preorder_right) {return null;}// 前序遍历中的第一个节点就是根节点int preorder_root = preorder_left;// 在中序遍历中定位根节点int inorder_root = indexMap.get(preorder[preorder_root]);// 先把根节点建立出来TreeNode root = new TreeNode(preorder[preorder_root]);// 得到左子树中的节点数目int size_left_subtree = inorder_root - inorder_left;// 递归地构造左子树,并连接到根节点// 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素root.left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);// 递归地构造右子树,并连接到根节点// 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素root.right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);return root;}public TreeNode buildTree(int[] preorder, int[] inorder) {int n = preorder.length;// 构造哈希映射,帮助我们快速定位根节点indexMap = new HashMap<Integer, Integer>();for (int i = 0; i < n; i++) {indexMap.put(inorder[i], i);}return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/solutions/255811/cong-qian-xu-yu-zhong-xu-bian-li-xu-lie-gou-zao-9/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

106.从中序与后序遍历序列构造二叉树todo

107.二叉树的层序遍历 II(正向输出然后再逆转)

题目描述:给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

思路:在遍历完一层节点之后,将存储该层节点值的列表添加到结果列表的头部。

108. 将有序数组转换为二叉搜索树(递归构造平衡二叉树搜索树)

中序遍历,总是选择中间位置左边的数字作为根节点

class Solution {public TreeNode sortedArrayToBST(int[] nums) {return helper(nums, 0, nums.length - 1);}public TreeNode helper(int[] nums, int left, int right) {if (left > right) {return null;}// 总是选择中间位置左边的数字作为根节点int mid = (left + right) / 2;TreeNode root = new TreeNode(nums[mid]);root.left = helper(nums, left, mid - 1);root.right = helper(nums, mid + 1, right);return root;}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/solutions/312607/jiang-you-xu-shu-zu-zhuan-huan-wei-er-cha-sou-s-33/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

109. 有序链表转换二叉搜索树

115. 不同的子序列(todo)

116. 填充每个节点的下一个右侧节点指针

118. 杨辉三角

第i行的第j个数=第i-1行的j-1个数 + 第i-1行的第j个数。注意下,左右边界都是1,就这么简单。

class Solution {public List<List<Integer>> generate(int numRows) {List<List<Integer>> ret = new ArrayList<List<Integer>>();for (int i = 0; i < numRows; ++i) {List<Integer> row = new ArrayList<Integer>();for (int j = 0; j <= i; ++j) {if (j == 0 || j == i) {row.add(1);} else {row.add(ret.get(i - 1).get(j - 1) + ret.get(i - 1).get(j));}}ret.add(row);}return ret;}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/pascals-triangle/solutions/510638/yang-hui-san-jiao-by-leetcode-solution-lew9/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

119. 杨辉三角 II

滚动数组优化

class Solution {public List<Integer> getRow(int rowIndex) {List<Integer> row = new ArrayList<Integer>();row.add(1);for (int i = 1; i <= rowIndex; ++i) {row.add(0);for (int j = i; j > 0; --j) {row.set(j, row.get(j) + row.get(j - 1));}}return row;}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/pascals-triangle-ii/solutions/601082/yang-hui-san-jiao-ii-by-leetcode-solutio-shuk/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

128. 最长连续序列(在hash表中不断枚举匹配x+1,x+2…x+y,判断x-1在hash表中是否存在就能避免重复的枚举)

我们考虑枚举数组中的每个数 x,考虑以其为起点,不断尝试匹配 x+1,x+2,是否存在,假设最长匹配到了 x+y,那么以 x 为起点的最长连续序列即为 x,x+1,x+2,⋯ ,x+y,其长度为 y+1,我们不断枚举并更新答案即可。

对于匹配的过程,暴力的方法是 O(n)遍历数组去看是否存在这个数,但其实更高效的方法是用一个哈希表存储数组中的数,这样查看一个数是否存在即能优化至 O(1)的时间复杂度。

仅仅是这样我们的算法时间复杂度最坏情况下还是会达到 O(n^2)(即外层需要枚举 O(n)个数,内层需要暴力匹配 O(n)次,无法满足题目的要求。但仔细分析这个过程,我们会发现其中执行了很多不必要的枚举,如果已知有一个 x,x+1,x+2,⋯ ,x+y的连续序列,而我们却重新从x+1,x+2或者是 x+y处开始尝试匹配,那么得到的结果肯定不会优于枚举 x为起点的答案,因此我们在外层循环的时候碰到这种情况跳过即可。

那么怎么判断是否跳过呢?由于我们要枚举的数 x 一定是在数组中不存在前驱数 x−1的,不然按照上面的分析我们会从 x−1开始尝试匹配,因此我们每次在哈希表中检查是否存在 x−1即能判断是否需要跳过了。

增加了判断跳过的逻辑之后,时间复杂度是多少呢?外层循环需要 O(n) 的时间复杂度,只有当一个数是连续序列的第一个数的情况下才会进入内层循环,然后在内层循环中匹配连续序列中的数,因此数组中的每个数只会进入内层循环一次。根据上述分析可知,总时间复杂度为O(n),符合题目要求。

134. 加油站

基于简单事实:如果x到不了y+1(但能到y),那么从x到y的任一点出发都不可能到达y+1。因为从其中任一点出发的话,相当于从0开始加油,而如果从x出发到该点则不一定是从0开始加油,可能还有剩余的油。既然不从0加油开车都到不了y+1,那么从0开始就更不可能到达y+1了…

最容易想到的解法是:从头到尾遍历每个加油站,并检查以该加油站为起点,最终能否行驶一周。我们可以通过减小被检查的加油站数目,来降低总的时间复杂度。

假设我们此前发现,从加油站 x出发,每经过一个加油站就加一次油(包括起始加油站),最后一个可以到达的加油站是 y(不妨设 x<y)

从上面的推导中,能够得出结论:从 x,y之间的任何一个加油站出发,都无法到达加油站 y 的下一个加油站。

在发现了这一个性质后,算法就很清楚了:我们首先检查第 0 个加油站,并试图判断能否环绕一周;如果不能,就从第一个无法到达的加油站开始继续检查。

136. 只出现一次的数字(异或运算的经典案例)

对于这道题,可使用位运算中的异或运算 ⊕。异或运算有以下三个性质。

  1. 任何数和 0 做异或运算,结果仍然是原来的数,即 a⊕0=a。
  2. 任何数和其自身做异或运算,结果是 0,即 a⊕a=0。
  3. 异或运算满足交换律和结合律,即 a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b

因此,数组中的全部元素的异或运算结果即为数组中只出现一次的数字。

class Solution {public int singleNumber(int[] nums) {int single = 0;for (int num : nums) {single ^= num;}return single;}
}

137. 只出现一次的数字 II(delete)

数字电路设计优化

class Solution {public int singleNumber(int[] nums) {int a = 0, b = 0;for (int num : nums) {b = ~a & (b ^ num);a = ~b & (a ^ num);}return b;}
}

138. 复制带随机指针的链表

第一次遍历原链表,每遍历到一个节点,都新建一个相同val的节点,然后使用HashMap建立旧链表节点和新链表节点的映射。第二次遍历时通过HashMap,建立新链表节点之间的next和random关系。

/*
// Definition for a Node.
class Node {int val;Node next;Node random;public Node(int val) {this.val = val;this.next = null;this.random = null;}
}
*/
public Node copyRandomList(Node head) {if(head == null){return null;}Node cur = head;HashMap<Node,Node> map = new HashMap<>();while(cur!=null){map.put(cur,new Node(cur.val));cur = cur.next;}cur=head;while(cur!=null){map.get(cur).next=map.get(cur.next);map.get(cur).random=map.get(cur.random);cur=cur.next;}return map.get(head);}

139. 单词拆分

141. 环形链表(龟兔赛跑算法-空间优化)

最容易想到的做法是hash表:我们可以使用哈希表来存储所有已经访问过的节点。每次我们到达一个节点,如果该节点已经存在于哈希表中,则说明该链表是环形链表,否则就将该节点加入哈希表中。重复这一过程,直到我们遍历完整个链表即可。

龟兔赛跑算法
假想「乌龟」和「兔子」在链表上移动,「兔子」跑得快,「乌龟」跑得慢。当「乌龟」和「兔子」从链表上的同一个节点开始移动时,如果该链表中没有环,那么「兔子」将一直处于「乌龟」的前方;如果该链表中有环,那么「兔子」会先于「乌龟」进入环,并且一直在环内移动。等到「乌龟」进入环时,由于「兔子」的速度快,它一定会在某个时刻与乌龟相遇,即套了「乌龟」若干圈。

我们可以根据上述思路来解决本题。具体地,我们定义两个指针,一快一慢。慢指针每次只移动一步,而快指针每次移动两步。初始时,慢指针在位置 head,而快指针在位置 head.next。这样一来,如果在移动的过程中,快指针反过来追上慢指针,就说明该链表为环形链表。否则快指针将到达链表尾部,该链表不为环形链表。

public class Solution {public boolean hasCycle(ListNode head) {if (head == null || head.next == null) {return false;}ListNode slow = head;ListNode fast = head.next;while (slow != fast) {if (fast == null || fast.next == null) {return false;}slow = slow.next;fast = fast.next.next;}return true;}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/linked-list-cycle/solutions/440042/huan-xing-lian-biao-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

142. 环形链表 II

比较简单的hash表做法

public class Solution {public ListNode detectCycle(ListNode head) {Set<ListNode> seen = new HashSet<ListNode>();while (head != null) {if (!seen.add(head)) {return head;}head = head.next;}return null;}
}

空间复杂度为O(1)的快慢指针做法

ps:为什么不能复用 环形链表 I的做法,因为你可以演示一下3->2->0->-4(->2):快慢指针首次相遇是在值0的位置。但实际题意要求是值为2的位置

快指针和慢指针从head出发,快指针每次走2步,慢指针每次走1步,当快指针和慢指针相遇后,再用第三个指针从节点出点,同时慢指针从相遇点出发,二者都每次走一步,相遇点即入环点(至于为什么可行:这是个数学问题:按照这个例子手动模拟一遍就会发现这个规律:严谨的就需要数学推导证明3->2->0->-4(->2))

感觉官解的双指针解释有点复杂。快慢指针的思路,两指针一开始都指向头指针,然后 fast 每次走两步,slow 每次走一步。记 fast 走过的步数为 f,slow 走过的步数为 s,链表环外长度为 a,环内长度为 b。这样两指针第一次相遇时,有 f = 2s,且 f = s + nb。 因此 s = nb。也就是说第一次相遇时,slow 走了若干个环的长度。我们还知道,环的入口应该走 a + nb 步,因此我们可以让第一次相遇后的 slow 指针走 a 步,这样 slow 就指向的环的入口。 那么 a 是多少呢? 我们不知道,但我们知道从头指针走到入口是 a 步,从 slow 第一次相遇的位置走到入口也是 a 步。 因此让 fast 指针在头指针的位置,slow 保持在第一次相遇位置,那么两个指针每次移动一步,当再次相遇,就说明走到了环形链表的入口位置。

public class Solution {public ListNode detectCycle(ListNode head) {ListNode fast = head, slow = head;while (true) {if (fast == null || fast.next == null) return null;fast = fast.next.next;slow = slow.next;if (fast == slow) break;}ListNode third = head;while (slow != third) {slow = slow.next;third = third.next;}return third;}
}作者:Krahets
链接:https://leetcode.cn/problems/linked-list-cycle-ii/solutions/12616/linked-list-cycle-ii-kuai-man-zhi-zhen-shuang-zhi-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

143. 重排链表

方法一:线性表
因为链表不支持下标访问,所以我们无法随机访问链表中任意位置的元素。

因此比较容易想到的一个方法是,我们利用线性表存储该链表,然后利用线性表可以下标访问的特点,直接按顺序访问指定元素,重建该链表即可。

方法二:寻找链表中点 + 链表逆序 + 合并链表(三个方法直接背下来)

class Solution {public void reorderList(ListNode head) {if (head == null) {return;}ListNode mid = middleNode(head);ListNode l1 = head;ListNode l2 = mid.next;mid.next = null;l2 = reverseList(l2);mergeList(l1, l2);}public ListNode middleNode(ListNode head) {ListNode slow = head;ListNode fast = head;while (fast.next != null && fast.next.next != null) {slow = slow.next;fast = fast.next.next;}return slow;}public ListNode reverseList(ListNode head) {ListNode prev = null;ListNode curr = head;while (curr != null) {ListNode nextTemp = curr.next;curr.next = prev;prev = curr;curr = nextTemp;}return prev;}public void mergeList(ListNode l1, ListNode l2) {ListNode l1_tmp;ListNode l2_tmp;while (l1 != null && l2 != null) {l1_tmp = l1.next;l2_tmp = l2.next;l1.next = l2;l1 = l1_tmp;l2.next = l1;l2 = l2_tmp;}}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/reorder-list/solutions/452867/zhong-pai-lian-biao-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

144. 二叉树的前序遍历/后序遍历

146. LRU 缓存

147. 对链表进行插入排序todo

148. 排序链表

150. 逆波兰表达式求值

151. 反转字符串中的单词(要求O(1))

class Solution {public String reverseWords(String s) {int start, end;                       // 每个单词的开始和结束索引(左闭右开)StringBuilder sb = new StringBuilder();for (int i = s.length() - 1; i >= 0; i--) {if (s.charAt(i) == ' ') continue;   //跳过空格end = i + 1;                        //找到结束索引while (i >= 0 && s.charAt(i) != ' ') i--;   //跳过空格start = i + 1;                      //找到开始索引         for (int j = start; j < end; j++)   //将每个单词按开始结束索引赋值到StringBuildersb.append(s.charAt(j));sb.append(' ');                     //加上单词间的空格}sb.deleteCharAt(sb.length() - 1);       //删掉最后一个多余的空格return sb.toString();}
}

169. 多数元素(投票算法)

229. 多数元素 II

224. 基本计算器

227. 基本计算器 II

232. 用栈实现队列

237. 删除链表中的节点

257. 二叉树的所有路径

class Solution {public List<String> binaryTreePaths(TreeNode root) {List<String> paths = new ArrayList<String>();constructPaths(root, "", paths);return paths;}public void constructPaths(TreeNode root, String path, List<String> paths) {if (root != null) {StringBuffer pathSB = new StringBuffer(path);pathSB.append(Integer.toString(root.val));if (root.left == null && root.right == null) {  // 当前节点是叶子节点paths.add(pathSB.toString());  // 把路径加入到答案中} else {pathSB.append("->");  // 当前节点不是叶子节点,继续递归遍历constructPaths(root.left, pathSB.toString(), paths);constructPaths(root.right, pathSB.toString(), paths);}}}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/binary-tree-paths/solutions/400326/er-cha-shu-de-suo-you-lu-jing-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

258. 各位相加(数学问题)

  1. 能够被9整除的整数,各位上的数字加起来也必然能被9整除,所以,连续累加起来,最终必然就是9。
  2. 不能被9整除的整数,各位上的数字加起来,结果对9取模,和初始数对9取摸,是一样的,所以,连续累加起来,最终必然就是初始数对9取摸。
int addDigits(int num)
{if(0 == num % 9){return 9;}return num % 9;
}

260. 只出现一次的数字 III(位运算-跳过)

263. 丑数

class Solution {public boolean isUgly(int n) {if (n <= 0) {return false;}int[] factors = {2, 3, 5};for (int factor : factors) {while (n % factor == 0) {n /= factor;}}return n == 1;}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/ugly-number/solutions/712106/chou-shu-by-leetcode-solution-fazd/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

264. 丑数 II

class Solution {public int nthUglyNumber(int n) {int[] dp = new int[n + 1];dp[1] = 1;int p2 = 1, p3 = 1, p5 = 1;for (int i = 2; i <= n; i++) {int num2 = dp[p2] * 2, num3 = dp[p3] * 3, num5 = dp[p5] * 5;dp[i] = Math.min(Math.min(num2, num3), num5);if (dp[i] == num2) {p2++;}if (dp[i] == num3) {p3++;}if (dp[i] == num5) {p5++;}}return dp[n];}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/ugly-number-ii/solutions/712102/chou-shu-ii-by-leetcode-solution-uoqd/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

268. 丢失的数字(原地哈希将空间复杂度降低为O(1)很6)

排序
hash
原地哈希

class Solution {public int missingNumber(int[] nums) {int n = nums.length;for (int i = 0; i < n; i++) {if (nums[i] != i && nums[i] < n) swap(nums, nums[i], i--);}for (int i = 0; i < n; i++) {if (nums[i] != i) return i;}return n;}void swap(int[] nums, int i, int j) {int c = nums[i];nums[i] = nums[j];nums[j] = c;}
}作者:宫水三叶
链接:https://leetcode.cn/problems/missing-number/solutions/1086545/gong-shui-san-xie-yi-ti-wu-jie-pai-xu-ji-te3s/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

274. H 指数(H 指数换一种理解就是:统计降序排列的数组中下标比下标值大的个数)

一个例子解释清楚算法在干什么

citations = [3,0,6,1,5]:首先排序6,5,3,1,0, 指数h初值设为0
然后计数:
6>(i=1) —h+1=1
5>(i=2) —h+1=2
3>=(i=3) —h+1=3
1<(i=3) —运行结束返回结果3

其实h-index的定义很简单,一个作者有h篇论文被引用次数不少于h,则这个作者的h-index即为h。题设给出的后一半定义”其余的 N - h 篇论文每篇被引用次数不多于 h 次“,只是一个补充说明——可以用反证法证明:如果我们查验了一个作者h篇文章,发现其h-index已经为h,如果剩余的文章还有引用次数大于h的,那他的h-index就不应是h,而应该至少是h+1。

反过来说,一个h-index为h的作者,想要提高自己的h-index,有两种方式——再发一篇文章,引用次数达到h + 1;或者,现有的文章,有一篇引用次数低于h的,突然被好多人引用,引用次数达到h次以上(但这种”翻红“估计非常少)。也就是说,引用次数本来就很多(>= h)的那些文章,再怎么传播也不会再增加这个作者的h-index。这是不是也是鼓励这个作者在本领域不断创造新的、高质量的研究成果呢~

因此,初见此题时,可能被这种补充说明带偏,其实在做题时只需要关注前半句即可:”一个作者有h篇论文被引用次数不少于h“。如果数组已排序,我们实际上是在就是在校验index(代表文章数x)和citations[index](代表有x篇文章拥有不低于/不高于某个引用次数)的大小关系。

首先我们可以将初始的 H 指数 h 设为 0,然后将引用次数排序,并且对排序后的数组从大到小遍历。

根据 H 指数的定义,如果当前 H 指数为 h 并且在遍历过程中找到当前值 citations[i]>h ,则说明我们找到了一篇被引用了至少 h+1 次的论文,所以将现有的 h 值加 1。继续遍历直到 h 无法继续增大。最后返回 h作为最终答案。

class Solution {public int hIndex(int[] citations) {Arrays.sort(citations);int h = 0, i = citations.length - 1; while (i >= 0 && citations[i] > h) {h++; i--;}return h;}
}

275. H 指数 II

采用二分法

class Solution {public int hIndex(int[] citations) {int n = citations.length;int left = 0, right = n - 1;while (left <= right) {int mid = left + (right - left) / 2;if (citations[mid] >= n - mid) {right = mid - 1;} else {left = mid + 1;}}return n - left;}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/h-index-ii/solutions/870989/h-zhi-shu-ii-by-leetcode-solution-si7h/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

279. 完全平方数

翻译一下题面 你有m种硬币,面额分别为1,4,9,16…你需要购买一个价格为n的商品,问最少花费几枚硬币 硬币问题的板子了

class Solution {public int numSquares(int n) {int[] f = new int[n + 1];for (int i = 1; i <= n; i++) {int minn = Integer.MAX_VALUE;for (int j = 1; j * j <= i; j++) {minn = Math.min(minn, f[i - j * j]);}f[i] = minn + 1;}return f[n];}
}class Solution {public int numSquares(int n) {int size = (int)Math.sqrt(n) + 5;int[] coins = new int[size];int[] dp = new int[n + 5];for(int i = 1; i < coins.length; i++){coins[i] = i * i;}//全用1填for(int i = 1; i <= n; i++){dp[i] = i;}for(int i = 2; i < coins.length; i++){int money = coins[i];for(int j = money; j <= n; j++){dp[j] = Math.min(dp[j],dp[j - coins[i]] + 1);}}return dp[n];}
}

283. 移动零(双指针)

使用双指针,左指针指向当前已经处理好的序列的尾部,右指针指向待处理序列的头部。

右指针不断向右移动,每次右指针指向非零数,则将左右指针对应的数交换,同时左指针右移。

287. 寻找重复数

将这个题目给的特殊的数组当作一个链表来看,数组的下标就是指向元素的指针,把数组的元素也看作指针。如 0 是指针,指向 nums[0],而 nums[0] 也是指针,指向 nums[nums[0]].

int point = 0;
while(true){point = nums[point]; // 等同于 next = next->next;
}

假设有这样一个样例:[1,2,3,4,5,6,7,8,9,5]。如果我们按照上面的循环下去就会得到这样一个路径:1 2 3 4 5 [6 7 8 9] [6 7 8 9] [6 7 8 9] . . .这样就有了一个环,也就是 6 7 8 9。point 会一直在环中循环的前进。

快慢指针-如何把数组当链表来处理

第一个错误版本:二分查找

根据题目特殊性:寻找可优化点

65310

1
2
3

290. 单词规律(将map的put性质发挥到了极致:如果key不存在,插入成功,返回null;如果key存在,返回之前对应的value)

class Solution {public boolean wordPattern(String pattern, String str) {String[] words = str.split(" ");//字符和单词是互相映射,数量必须相等if (words.length != pattern.length()) {return false;}Map<Object, Integer> map = new HashMap<>();for (Integer i = 0; i < words.length; i++) {/*如果key不存在,插入成功,返回null;如果key存在,返回之前对应的value。以pattern = "abba", str = "dog cat cat dog"为例,第1次:map.put('a',0)返回null,map.put("dog",0)返回null,两者相等;第2次:map.put('b',1)返回null,map.put("cat",1)返回null,两者相等;第3次:map.put('b',2)返回1,map.put("cat",2)返回1,两者相等;第4次:map.put('a',3)返回0,map.put("dog",3)返回0,两者相等,结果为 true。以pattern = "abba", str = "dog cat cat fish"为例,第1次:map.put('a',0)返回null,map.put("dog",0)返回null,两者相等;第2次:map.put('b',1)返回null,map.put("cat",1)返回null,两者相等;第3次:map.put('b',2)返回1,map.put("cat",2)返回1,两者相等;第4次:map.put('a',3)返回0,map.put("fish",3)返回null,两者不相等,结果为 false。*/if (map.put(pattern.charAt(i), i) != map.put(words[i], i)) {return false;}}return true;}
}

287. 寻找重复数

289. 生命游戏todo

292. Nim 游戏

数学推理
这道题,显而易见的是1、2、3块石头你能一次全拿走。但是4块石头,你无论怎么拿,朋友肯定能拿走剩下的所有石头 因此只要最后剩下4块石头,先手必输

我们进一步推理

既然剩下四块石头,先手必输,那么我只要保证每次只剩下4的倍数块石头,并且朋友拿,最后剩下只4块石头时我就必赢,换句话说,只要我在有4的倍数块石头时拿石头我必输

我们再想,只有在开始有4的倍数块石头时我才能最后4块石头先手拿,因为当n%4为1、2、3时我只要把多出来的这几个拿走,朋友就先手拿了

到了这一步,已经思路很清晰了,n%4==0时返回false,否则返回true

class Solution {public boolean canWinNim(int n) {return n % 4 != 0;}
}

299. 猜数字游戏

根据题意,我们可以对 secret 和 guess进行诸位比较,统计公牛数量 a和奶牛数量 b。

对于字符相同的位置,我们可以直接对 a 进行自增;对于字符不同的位置,使用「哈希表」进行分别统计 secret 和 guess 的词频,某个数字 x 在两者词频中的较小值,即为该数字对应的奶牛数量,统计所有数字 [0,9] 的奶牛数量总和即为 b

hash表是用int[10]来表示的map[‘9’]=1,map[‘9’]=2这样c2= guess.charAt(i) - ‘0’【c - ‘0’ 就相当于计算c的实际数值,例如 c 是 ‘1’, 则 c - ‘0’ = 1, 把字符值转为数字值了】

class Solution {public String getHint(String secret, String guess) {int n = secret.length();int a = 0, b = 0;int[] cnt1 = new int[10], cnt2 = new int[10];for (int i = 0; i < n; i++) {int c1 = secret.charAt(i) - '0', c2= guess.charAt(i) - '0';if (c1 == c2) {a++;} else {cnt1[c1]++;cnt2[c2]++;}}for (int i = 0; i < 10; i++) b += Math.min(cnt1[i], cnt2[i]);return a + "A" + b + "B";}
}作者:宫水三叶
链接:https://leetcode.cn/problems/bulls-and-cows/solutions/1089829/gong-shui-san-xie-jian-dan-mo-ni-ti-by-a-tdhs/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

300. 最长递增子序列

附加

  • 排序
    归并/快排/堆排

  • 动态规划
    最长递增子序列
    最长连续递增子序列
    最大连续子序列的和(连续子数组的最大和)
    最长公共子序列
    最长公共连续子序列
    最长不重复子串

算法刷题专辑60分版本相关推荐

  1. 算法框架专辑60分版本

    文章目录 框架 动态规划 框架 经典例题 01背包&完全背包 拓展例题 爬楼梯 凑硬币/零钱兑换(完全背包) 丑数 最长递增子序列 最长公共子序列 子数组的最大和 使用最小花费爬楼梯---== ...

  2. Github最强算法刷题笔记.pdf

    资料一 昨晚逛GitHub,无意中看到一位大佬(https://github.com/halfrost)的算法刷题笔记,感觉发现了宝藏!有些小伙伴可能已经发现了,但咱这里还是忍不住安利一波,怕有些小伙 ...

  3. 神了,无意中发现一位1500道的2021LeetCode算法刷题pdf笔记

    昨晚逛GitHub,无意中看到一位大佬的算法刷题笔记,感觉发现了宝藏!有些小伙伴可能已经发现了,但咱这里还是忍不住安利一波,怕有些小伙伴没有看到. 关于算法刷题的困惑和疑问也经常听朋友们提及.这份笔记 ...

  4. 算法刷题-数论-试除法求约数、约数个数、约数之和、最大公约数(辗转相除法)

    文章目录 acwing869. 试除法求约数 acwing870. 约数个数 acwing871. 约数之和 acwing872. 最大公约数 acwing869. 试除法求约数 acwing869. ...

  5. 90页Numpy精华、算法刷题44天等内容整理

    你好,我是 zhenguo 今天总结最近推送过的项目.案例和资料相关PDF 这些资料中,有一部分是我耗费好几个月原创的,真的非常辛苦! 如<施工专题20篇.pdf>目前总阅读量已经达到 1 ...

  6. 找到所有数组中消失的数字_【一点资讯】千万程序员的呼声:面试如何拿到大厂Offer?这份阅读量超过11W+的算法刷题宝典请你原地查收 www.yidianzixun.com...

    如何才能通过面试拿到大厂Offer? "刷leetcode!" 这是我听到最多的回答! 现在越来越多的人应聘工作时都得先刷个几十百来道题,不刷题感觉都过不了面试. 无论是面测试.算 ...

  7. 搬砖试金石!github星标7W算法刷题宝典,还愁拿不下大厂offer?

    前言 这几年IT技术蓬勃发展,日新月异,对技术人才的需求日益增长,程序员招聘市场也如火如荼.在有限的三五轮面试中,国外流行让面试者编程解决某些数据结构和算法的题目,通过观察面试者编码的熟练程度.思考的 ...

  8. 算法刷题路线总结与相关资料分享

    算法刷题路线总结与相关资料分享 前言 一.算法刷题路线总结 二.算法题刷题步骤 三.基础数据结构知识汇总 1.时间复杂度 2.空间复杂度 3.线性表 4.栈与队列 5.树 四.基础算法知识汇总 1.递 ...

  9. LeetCode刷题之575.分糖果

    LeetCode刷题之575.分糖果 我不知道将去向何方,但我已在路上! 时光匆匆,虽未曾谋面,却相遇于斯,实在是莫大的缘分,感谢您的到访 ! 题目: 给定一个偶数长度的数组,其中不同的数字代表着不同 ...

最新文章

  1. Linux——主流发行版本
  2. 将10000H-1000FH这段空间当做栈,初始状态栈是空的,设置AX=001AH,BX=001BH,利用栈,交换AX和BX的数据
  3. POJ 1200 Crazy Search(RK)
  4. mui-scroll-wrapper mui-scroll 内容增多不出滚动条
  5. 恩智浦发布新款跨界处理器
  6. 网上课程之实例讲解(2)
  7. java 日志时间格式_java.util.logging.Logger 使用中关于时间格式的问题
  8. mysql explain select_type
  9. 在 Mac上接收、暂停或停止接收通知操作方法
  10. 将mysql服务从C盘(原),安装到新路径D盘下(其中的数据一并迁移)
  11. 终于讲透了,史上最详细的RS485自动收发电路你一定要掌握
  12. 锐浪报表数据源access_锐浪报表应用系列三
  13. 服务器cpu天梯图_12月更新最新CPU天梯图amp;显卡天梯图,选购电脑必看(含台式与笔记本电脑CPUamp;显卡)含机型推荐...
  14. 【First-order Methods】 5 Smoothness and Strong Convexity
  15. MySQL:指定索引+事务+存储引擎的配置 开发必备 天呐!为什么会有索引这种东西
  16. 【3】三剑客:grep
  17. Java并发编程之Exchanger
  18. COOX基础培训之DiagTool
  19. 常规批复试录取浙大MBA的幸运儿经验分享
  20. 关注和实际不符_商品房层高与合同约定不符的相关法律问题

热门文章

  1. nginxlocation二级目录
  2. 【论文阅读】PU-GAN:点云上采样的对抗生成网络
  3. LSM-Tree:原理与介绍
  4. Markdown使用说明
  5. Origin?Steam?试着买这些游戏就对了。
  6. android draw八卦图
  7. 电商平台数据解锁网红零食销量密码
  8. oracle添加索引的规则,Oracle 创建索引的基本规则总结
  9. Kurento Media Server源码编译
  10. 计算机 游戏13关,优秀游戏盘点:22款PC平台玩家必玩游戏 大作齐聚