1. Two Sum

leetcode链接: https://oj.leetcode.com/problems/two-sum/

最基础的一道题,方法很多,用HashMap存pair是一种(HashSet和HashMap的方法在这里原理是一样的)。也可以sort the whole array first,then use two pointers, one start from the left side, the other from the right side. if array[left]+array[right]>target, move the right index to the left by 1, 小于的话同理. 这里给一个HashMap的方法。

 1 public int[] twoSum(int[] numbers, int target) {
 2    HashMap<Integer, Integer>  map = new HashMap<Integer, Integer>();
 3    int[] result = new int[2];
 4    for(int i = 0; i < numbers.length; i++) {
 5      if(map.containsKey(numbers[i])) {
 6        int index = map.get(numbers[i]);
 7        result[0] = index + 1;
 8        result[1] = i + 1;
 9        break;
10      } else {
11        map.put(target - numbers[i], i);
12      }
13    }
14    return result;
15 }    

2. Median of Two sorted arrays

leetcode链接: https://oj.leetcode.com/problems/median-of-two-sorted-arrays/

首先,比较暴力的方法是统计两个数组的长度(奇数长度有一个median,偶数长度是最中间的两个数的均值),然后两个数组各设置一个index, 谁小,谁的index++,直到两个index走的总长度达到了median所需的长度。这个是O(n)的复杂度。进一步想,数组里找某个数的问题很容易往binary search上面考。这题也不例外。只不过这道题对于边界的控制需要小心,一下写出bug free的代码还是挺有难度的。

关键的是把这个问题转化为第k小的问题。只不过最终找的这个k其实是median。转化为第k小的问题有一个好处,比较好设计成一个recursion的函数。recursion,第一步想清楚base case, 这个recursion里面,第k小的数、这个k是可能会变化的。变化到最后,剩下的某个数组为空,或者k==1的时候,就找到了我们想要的结果,recursion就走到头了。第二步想清楚recursion rule。每次判断剩余的A和B两个数组各自的median,通过比较他们的大小,我们要么舍弃A的前半段和B的后半段,要么舍弃A的后半段和B的前半段。每一个情况又分为两种,如果舍弃的是某个数组的后半段,我们要找的仍然是剩下的元素中间的第k小的数,k不变。如果舍弃的是某个数组的前半段,那么我们的k就要发生变化了,传进下一层recursion的k参数就要发生变化。综上,我们实际上每层recursion会分四种情况讨论。具体的我在下面的代码里做了注释。

 1 public double findMedianSortedArrays(int[] A, int[] B) {
 2      int lengthA = A.length;
 3      int lengthB = B.length;
 4      if((lengthA + lengthB) % 2 == 0) {
 5          double r1 = (double)findM(A, 0, lengthA, B, 0, lengthB, (lengthA + lengthB) / 2);
 6          double r2 = (double)findM(A, 0, lengthA, B, 0, lengthB, (lengthA + lengthB) / 2 + 1);
 7          return (r1 + r2) / 2;
 8     } else {
 9          return findM(A, 0, lengthA, B, 0, lengthB, (lengthA + lengthB) / 2 + 1);
10     }
11 }
12
13 public int findM(int[] A, int startA, int endA, int[] B, int startB, int endB, int k) {
14 //转换为第k小数的问题
15     int n = endA - startA;
16     int m = endB - startB;
17     if(n <= 0) {//corner case & base case of recursion
18          return B[startB + k - 1];
19     }
20     if(m <= 0) {//corner case & base case of recursion
21          return A[startA + k - 1]
22     }
23     if(k == 1) {//corner case & recursion case of recursion
24          return A[startA] < B[startB] ? A[startA] : B[startB];
25     }
26     int midA = (startA + endA) / 2;
27     int midB = (startB + endB) / 2;
28     if(A[midA] <= B[midB]) {// the target will appear at the first half of A, or the second half of B
29          if(n / 2 + m / 2 + 1 >= k) {// if in second half of B, k will not change, because we will not cut any number smaller than target
30               return findM(A, startA, endA, B, startB, midB, k);
31          } else {// if in the first half of A, we will cut all the number in the first half, the next step is: find the (k-n/2-1)th smallest number
32               return findM(A, mid + 1, endA, B, startB, endB, k - n / 2 - 1);
33      } else {
34          if(n / 2 + m / 2 + 1 >= k) {
35               return findM(A, startA, midA, B, startB, endB, k);
36           } else {
37               return findM(A, startA, endA, B, midB + 1, endB, k - m / 2 -1);
38          }
39     }
40 }           

3. Longest Substring Without Repeating Characters

leetcode链接: https://oj.leetcode.com/problems/longest-substring-without-repeating-characters/

首先能直观的想到暴力的方法,两个指针标记子串的头和尾,hashset来检查是否有重复,两层for循环头和尾,hashset检测到重复以后退出尾部指针的循环,比较与global的大小并更新。但是这里时间复杂度是O(n^2)。一个更好的办法是开辟一个256的数组,作用其实就是个字典表

 1 public int lengthOfLongestSubstring(String s) {
 2      int[] charMap = new int[256];
 3      Arrays.fill(charMap, -1);
 4      int i = 0;
 5      int maxLen = 0;
 6      for(int j = 0; j < s.length(); j++) {
 7           if(charMap[s.charAt(j)] >= i) {
 8                i = charMap[s.charAt(j)] + 1;
 9           }
10           charMap[s.charAt(j)] = i;
11           maxLen = Math.max(j - i + 1, maxLen);
12     }
13     return maxLen;
14 }

4. Add Two Numbers

leetcode链接: https://oj.leetcode.com/problems/add-two-numbers/

这个题思路很直观,两个链表各一个指针用来读值。另外需要考虑几件事,1. 当某个链表读到头的时候怎么办,2. 这种合并链表的题最好设置dummyHead,3. 最后的最后,如果依然有进位,别把它忘了。其他倒是没啥了。O(m+n)的复杂度

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {int carry = 0;ListNode newHead = new ListNode(0);ListNode p1 = l1;ListNode p2 = l2;ListNode p3 = newHead;while(p1 != null || p2 != null) {if(p1 != null) {carry += p1.val;p1 = p1.next;}  if(p2 != null) {carry += p2.val;p2 = p2.next;}p3.next = new ListNode(carry % 10);p3 = p3.next;carry /= 10;}  if(carry == 1) {p3.next = new ListNode(1);}return newHead.next;
}

5. Longest Palindromic Substring

leetcode链接: https://oj.leetcode.com/problems/longest-palindromic-substring/

这道题思路仍然很直接,循环扫描每个字符,每次从中心开花,找palindrome。但是有几点需要注意:

1. palindrome分为两种,一种是中心有一个元素,然后两边元素满足palindrome,另一种是中心有两个元素,这两个元素相等,然后以他俩为中心两边palindrome

2. corner case:写辅助函数的时候,是否在palindrome为1的时候合法?len2里面,(s, i, i+1),i+1这个参数貌似越界了,真的越界了么,会throw exception么?可以自己把特殊情况带进去,在演草纸上划拉一下,验证下。

3. 审题。题目需要返回的结果是个最长palindrome的substring,而不是int length。所以我们需要在找到更大长度的时候更新start和end这两个index。

public String longestPalindrome(String s) {int start = 0;int 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);
}
public int expandAroundCenter(String s, int left, int right) {int L = left;int R = right;while(L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {L--;R++;}  return R - L - 1;
}

6. ZigZag Conversion

leetcode链接: https://oj.leetcode.com/problems/zigzag-conversion/

其实是挺没意思的一道题。纯math。在纸上画一个5 row的情况。找到规律即可。注意数组下标的操作不要越界,算清楚。

public String convert(String s, int nRows) {if(s == null || s.length() == 0 || nRows <= 0) {return "";}if(nRows == 1) {return s;}StringBuilder result = new StringBuilder();int size = 2 * nRows - 2;for(int i = 0; i < nRows; i++) {for(int j = i; j < s.length(); j += size) {result.append(s.charAt(j));if(i != 0 && i != nRows - 1) {int temp = j + size - 2 * i;if(temp < s.length()) {result.append(s.charAt(temp));}}}}return result.toString();
}

7. Reverse Integer

leetcode链接: https://oj.leetcode.com/problems/reverse-integer/

最直观的方法是把integer变成charArray,然后把charArray给reverse。需要的额外空间会多一些。下面的方法是直接对数字进行处理。注意会有很多corner case,都是计算机语言对于数字存储的细节方面的知识了。

public int reverse(int x) {if(x == Integer.MIN_VALUE) {return 0;}  int num = Math.abs(x);int result = 0;while(num != 0) {if(result > (Integer.MAX_VALUE - num % 10) / 10) {return 0;}result = result * 10 + num % 10;num /= 10;}return x > 0 ? result : -result;
}                

8. String to Integer(atoi)

leetcode链接:https://oj.leetcode.com/problems/string-to-integer-atoi/

没什么具体的算法思路,考的仍然是对语言细节的掌握和corner case的敏感度。

public static final int maxDivBy10 = Integer.MAX_VALUE / 10;public int atoi(String str) {int i = 0;int n = str.length();while(i < n && Character.isWhitespace(str.charAt(i))) {i++; //regardless of the heading white space
    } int sigh = 1;if(i < n && str.charAt(i) == '+') {i++;} else if(i < n && str.charAt(i) == '-') {sign = -1;i++;}int num = 0;while(i < n && Character.isDigit(str.charAt(i))) {int digit = Character.getNumericValue(str.charAt(i));if(num > maxDivBy10 || num == maxDivBy10 && digit >= 8) {return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;}num = num * 10 + digit;i++;}return sign * num;
}  

9. Palindrome Number

leetcode链接: https://oj.leetcode.com/problems/palindrome-number/

这个题要求不要有额外的空间。所以转化成字符串比较就行不同了。那就只能每次剥离这个数当前的首尾然后比较。为了取到第一位,我们需要首先生成一个大除数。然后开始循环判断是否palindrome,不要忘了每次大除数要自除100,因为剥离了两个数字。

public boolean isPalindrome(int x) {if(x < 0) {return false;  }int div = 1;while(x / div >= 10) {div *= 10;}while(x != 0) {int left = x / div;int right = x % 10;if(left  != right) {return false;}x = (x % div) / 10;div /= 100;}return true;
}

10. Regular Expression Matching

leetcode链接: https://oj.leetcode.com/problems/regular-expression-matching/

recursion的方法一层一层判断。需要注意的是base case比较多。这也是由于regular expression匹配的情况比较多导致的。

public boolean isMatch(String s, String p) {if(p.length() == 0) {return s.length() == 0;}  if(p.length() == 1) {return (s.length() == 1) && (p.charAt(0) == s.charAt(0) || p.charAt(0) == '.');}if(p.charAt(1) != '*') {if(s.length() == 0) {return false;} else {return (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.') && isMatch(s.substring(1), p.substring(1));         }} else {while(s.length() > 0 && (p.charAt(0) == s.charAt(0)) || p.charAt(0) == '.')  {if(isMatch(s, p.substring(2))) {return true;}s = s.substring(1);}return isMatch(s, p.substring(2));}
}

 总结leetcode的前十道题,个人感觉比较好,值得回味的应该是第2,3,4,10题。

11. Container with most water

leetcode链接:https://leetcode.com/problems/container-with-most-water/

这道题需要审题。和trap water是有区别的。trap water是高低不平的一排区间,问能存多少水。而这道题只需要考虑两条边界,中间可以认为是空的,可以存水。实际上难度大大降低。只需要左右两个pointer即可。

 1 public int maxArea(int[] height) {
 2      if(height.length <= 1) {
 3            return 0;
 4      }
 5      int left = 0;
 6      int right = height.length - 1;
 7      int max = 0;
 8      while(left < right) {
 9            max = Math.max(max, (right - left) * Math.min(height[left], height[right]));
10            if(height[left] < height[right]) {
11                  left++;
12            }  else {
13                  right++;
14            }
15     }
16     return max;
17 }

14. Longest common prefix

leetcode链接: https://leetcode.com/problems/longest-common-prefix/

public String longestCommonPrefix(String[] strs) {if(strs == null || strs.length == 0) {return "";}String prefix = strs[0];for(int i = 1; i < strs.length; i++) {int j = 0;for(; j < strs[i].length() && j < prefix.length(); j++) {if(prefix.charAt(j) != strs[i].charAt(j)) {break;}}prefix = prefix.substring(0, j);if(prefix.length() == 0) {break;}}return prefix;
}

15. 3 Sum

leetcode链接: https://leetcode.com/problems/3sum/

其实这个3Sum的解法很直接,用3个指针追踪三个数凑出所需的数。唯一需要注意的是这道题需要一个deduplication的过程。

这个deduplication用hashset同样可以解决,不过这个解法更精炼一些。

public List<List<Integer>> threeSum(int[] num) {List<List<Integer>> result = new ArrayList<List<Integer>>();if(num.length < 3 || num == null) {return result;}  Arrays.sort(num);for(int i = 0; i < num.length - 2; i++) {if(i == 0 || num[i] > num > num[i - 1]) {int j = i + 1;int k = num.length - 1;while(j < k) {if(num[j] + num[k] == -num[i]) {ArrayList<Integer> list = new ArrayList<Integer>();list.add(num[i]);list.add(num[j]);list.add(num[k]);k--;j++;while(j < k && num[k] == num[k + 1]) {k--;}while(j < k && num[j] == num[j - 1]) {j++;}} else if(num[j] + num[k] > -num[i]) {k--;} else {j++;}}}}
}     

16. 3Sum Closest

leetcode链接: https://leetcode.com/problems/3sum-closest/

先排序(很重要), 然后循环三个指针, 如果diff出现比min还小, 更新min。

 1 public int threeSumClosest(int[] num, int target) {
 2      int result = 0;
 3      int min = Integer.MAX_VALUE;
 4      Arrays.sort(num);
 5      for(int i = 0; i < num.length; i++) {
 6           int j = i + 1;
 7           int k = num.length - 1;
 8           while (j < k) {
 9                 int sum = num[i] + num[j] + num[k];
10                 int diff = Math.abs(target - sum);
11                 if(diff == 0) {
12                       return sum;
13                 }
14                 if(diff < min) {
15                       min = diff;
16                       result = sum;
17                 }
18                 if(sum <= target) {
19                       j++;
20                 } else {
21                       k--;
22                 }
23           }
24      }
25      return result;
26 }

顺便推广自己的微店---美国加拿大留学申请咨询 http://weidian.com/s/316012464?wfr=c

转载于:https://www.cnblogs.com/jianghewade/p/4290007.html

Leetcode刷题笔记(部分非原创)(1-20题)相关推荐

  1. css总结-笔记--部分非原创--属于资源整合

    文章目录 一.css基础教程 1.选择器等级 1.1层叠次序 1.2css三大特性 层叠性原则 继承性 优先级 2.基础语法 2.1声明 2.2值的写法和单位 2.2.1颜色的几种写法(用红色举例) ...

  2. char java 回文_LeetCode刷题笔记(Java)---第1-18题

    题目来自LeetCode 文章目录 全部章节 1-18题 19-40题 41-60题 61-80题 81-100题 101-120题 121-140题 1.两数之和 2.两数相加 3.无重复字符串的最 ...

  3. 考研数学如何整理错题笔记?140分学长总结的模板,拿走直接用(含错题笔记)

    考研数学如何整理错题笔记?140分学长总结的模板,拿走直接用(含错题笔记) 数学错题笔记 2021<考研数学接力题典1800>勘误表(附学霸高分笔记) 2020考研初试成绩已经公布了,对于 ...

  4. buuctf-MISC篇做题笔记(2)

    buuctf-MISC篇做题笔记(2) 第七题:基础破解 先看题目提示,可能也要暴力破解 打开后是RAR文件,需要密码 我是用RARpassword暴力破解,且根据题意已知是四位纯数字密码,设置破解的 ...

  5. LeetCode部分刷题笔记!!!JavaScript!!!

    详细解说请看视频JS老毕:人人都能看得懂的Leetcode力扣刷题教程合集 边看视频边记录笔记!!!部分题目在视频中无! 文章目录 LeetCode第1题:1. 两数之和 LeetCode第2题:2. ...

  6. LeetCode刷题笔记2——数组2

    LeetCode刷题笔记2--数组2 重塑数组 题目 在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原 ...

  7. LeetCode《算法入门》刷题笔记(31 题全)

    LeetCode<算法入门>刷题笔记(31 题全) 二分查找 1. 二分查找 _解法1:二分搜索(迭代) 解法2:二分搜索(递归) 2. 第一个错误的版本 _解法1:二分 3. 搜索插入位 ...

  8. leetcode分类刷题笔记

    leetcode分类刷题笔记--基于python3 写在前面 1.做题如果实在想不出时间复杂度比较优的解法,可以先写出暴力解法,尝试在其基础上优化 2.排序.双指针.二分等--经常可以优化时间复杂度 ...

  9. LeetCode刷题笔记(算法思想 四)

    LeetCode刷题笔记(算法思想 四) 七.动态规划 斐波那契数列 70. 爬楼梯 198. 打家劫舍 213. 打家劫舍 II 信件错排 母牛生产 矩阵路径 64. 最小路径和 62. 不同路径 ...

  10. 卷进大厂系列之LeetCode刷题笔记:二分查找(简单)

    LeetCode刷题笔记:二分查找(简单) 学算法,刷力扣,加油卷,进大厂! 题目描述 涉及算法 题目解答 学算法,刷力扣,加油卷,进大厂! 题目描述 力扣题目链接 给定一个 n 个元素有序的(升序) ...

最新文章

  1. python拿来干嘛-Python是什么 Python的用处
  2. 密码协议(三)裁决协议和自动执行协议
  3. 数据挖掘系列(4)使用weka做关联规则挖掘
  4. 深度学习:tensorflow的简单用法,tensorflow实现SVM
  5. 红帽子linux改ip命令,RedHat 7 修改IP地址
  6. gan神经网络_神经联觉:当艺术遇见GAN
  7. ES6 学习笔记(一)let,const和解构赋值
  8. python的编程方式模块化_我的Python笔记·模块化编程(一)
  9. 【带着canvas去流浪(13)】用Three.js制作简易的MARVEL片头动画(下)
  10. 2021年软考真题系统分析师真题答案解析汇总
  11. 虚拟机您的计算机无法启动,一键解决win10虚拟机无法启动的问题
  12. 百度网盘下载一直请求中问题解决
  13. nabcd分析解谜类rpg游戏
  14. 解决:openstack-dashboard-登陆后显示报错
  15. 聚类——K均值简介及Python实现
  16. Activities介绍
  17. SolidWorks Premium 白金版
  18. 五子棋 手打稍加改变自慕课网hyman
  19. 无法割舍的乡情--去外公家
  20. 互联网名称与数字地址分配机构ICANN简介

热门文章

  1. 快闪族 - 百度百科
  2. Linux命令之shutdown
  3. 计蒜客NOIP2017提高组模拟赛(三)day2-小区划分
  4. C++字符串空格替换题
  5. 洛谷-神奇的幻方-NOIP2015提高组复赛
  6. AlarmManager.setRepeating将不再准确
  7. myeclipse 保存失败
  8. libusb的使用教程和例子
  9. zipfile.BadZipFile: File is not a zip file
  10. 我遇到的JPA中事务回滚的问题