1.Two Sum
Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution, and you may not use the same element twice.
使用hash
public int[] twoSum(int[] nums, int target) { int[] res = new int[2]; if (nums == null || nums.length < 2) { return res; } HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); int n = nums.length; for (int i = 0; i < n; i++) { if (map.containsKey(target - nums[i])) { res[0] = map.get(target - nums[i]); res[1] = i; return res; } map.put(nums[i], i); } return res; }
2.Add Two Numbers
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself. Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8
dummyHead cur控制。carry携带进位
def addTwoNumbers(self, l1, l2): """ :type l1: ListNode :type l2: ListNode :rtype: ListNode """ dummyHead = ListNode(0) cur = dummyHead carry = 0 while (l1 or l2): sum = 0 if l1: sum += l1.val l1 = l1.next if l2: sum += l2.val l2 = l2.next sum += carry carry = sum / 10 cur.next = ListNode(sum % 10) cur = cur.next if carry != 0: cur.next = ListNode(carry) return dummyHead.next
3.Longest Substring Without Repeating Characters --- not bug free
Given a string, find the length of the longest substring without repeating characters. Examples: Given "abcabcbb", the answer is "abc", which the length is 3. Given "bbbbb", the answer is "b", with the length of 1. Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.
使用数组充当map
注意:left的更新规则,可能有些出现过的点上次出现的位置还在left的左边。最后也需要一个max的操作
1 public int lengthOfLongestSubstring(String s) { 2 if (s == null || s.length() == 0) { 3 return 0; 4 } 5 int[] map = new int[128]; 6 Arrays.fill(map, -1); 7 char[] chars = s.toCharArray(); 8 int n = s.length(); 9 int left = 0; 10 int right = 0; 11 int res = 0; 12 while (right < n) { 13 if (map[chars[right]] == -1) { 14 map[chars[right]] = right; 15 right++; 16 } else { 17 res = Math.max(res, right - left); 18 left = Math.max(left, map[chars[right]] + 1); // Attention! 19 map[chars[right]] = right; 20 right++; 21 } 22 } 23 res = Math.max(res, right - left); 24 return res; // Attention! 25 }
4.Median of Two Sorted Arrays
There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
findTopK。检测四个条件:是否一个为空了,是否找第一个,是否其中一个不够 k / 2 了,谁大谁小。
public double findMedianSortedArrays(int[] nums1, int[] nums2) { if (nums1 == null || nums2 == null) { return 0.0; } int m = nums1.length; int n = nums2.length; int total = m + n; if (total % 2 == 0) { return (findTopK(nums1, 0, m - 1, nums2, 0, n - 1, total / 2) + findTopK(nums1, 0, m - 1, nums2, 0, n - 1, total / 2 + 1)) / 2.0; } else { return (double)findTopK(nums1, 0, m -1, nums2, 0, n - 1, total / 2 + 1); } } public int findTopK(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k) { if (start1 > end1) { return nums2[start2 + k - 1]; } if (start2 > end2) { return nums1[start1 + k - 1]; } if (k == 1) { return Math.min(nums1[start1], nums2[start2]); } if (start1 + k / 2 - 1 > end1) { return findTopK(nums1, start1, end1, nums2, start2 + k / 2, end2, k - k / 2); } if (start2 + k / 2 - 1 > end2) { return findTopK(nums1, start1 + k / 2, end1, nums2, start2, end2, k - k / 2); } if (nums1[start1 + k / 2 - 1] > nums2[start2 + k / 2 - 1]) { return findTopK(nums1, start1, end1, nums2, start2 + k / 2, end2, k - k / 2); } else { return findTopK(nums1, start1 + k / 2, end1, nums2, start2, end2, k - k / 2); } }
5.Longest Palindromic Substring
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
以每个点为中心扩张
global low global res def longestPalindrome(self, s): """ :type s: str :rtype: str """ global low global res low = 0 res = 1 if not s: return s n = len(s) for i in range(n - 1): self.test(s, i, i) self.test(s, i, i + 1) return s[low : low + res] def test(self, s, i, j): n = len(s) global res global low while (i >= 0 and j < n and s[i] == s[j]): i -= 1 j += 1 if (j - i - 1 > res): res = j - i - 1 low = i + 1
dp dp[i][j]表示[i, j]子串是不是回文串。全局记录一个最大最小
def longestPalindrome(self, s): """ :type s: str :rtype: str """ if not s: return s n = len(s) start = 0 end = 0 dp = [[False for col in range(n)] for row in range(n)] # dp[i][j]表示[i, j]是否是回文串 for i in range(n): dp[i][i] = True for k in range(1, n): for i in range(n - k): j = i + k if (s[i] == s[j] and (k == 1 or dp[i + 1][j - 1])): dp[i][j] = True if (end - start < k) : start = i end = j return s[start : end + 1]
6.ZigZag Conversion
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) P A H N A P L S I I G Y I R And then read line by line: "PAHNAPLSIIGYIR" Write the code that will take a string and make this conversion given a number of rows: string convert(string text, int nRows); convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".
每一行用一个StringBuilder 来记录
public String convert(String s, int numRows) { if (s == null || s.length() <= numRows || numRows == 1) { return s; } StringBuilder[] sb = new StringBuilder[numRows]; for (int j = 0; j < numRows; j++) { sb[j] = new StringBuilder(); } char[] chars = s.toCharArray(); int n = s.length(); int i = 0; while (i < n) { for (int j = 0; j < numRows && i < n; j++) { sb[j].append(chars[i++]); } for (int j = numRows - 2; j > 0 && i < n; j--) { sb[j].append(chars[i++]); } } for (int j = 1; j < numRows; j++) { sb[0].append(sb[j]); } return sb[0].toString(); }
7.Reverse Integer
Reverse digits of an integer. Example1: x = 123, return 321 Example2: x = -123, return -321
直接使用负数来计算也是可以的。注意越界单独处理就可以了。
public int reverse(int x) { long res = 0; while (x != 0) { int temp = x % 10; res = res * 10 + temp; if (res > Integer.MAX_VALUE || res < Integer.MIN_VALUE) { return 0; } x /= 10; } return (int)res; }
8.String to Integer (atoi)
首位空格,非数字,越界, 正负号
public int myAtoi(String str) { if (str == null) { return 0; } str = str.trim(); if (str.length() == 0) { return 0; } char[] chars = str.toCharArray(); long res = 0; int start = 0; boolean flag = false; if (chars[0] == '-') { flag = true; start = 1; } if (chars[0] == '+') { start = 1; } int n = str.length(); while (start < n) { if (Character.isDigit(chars[start])) { res = 10 * res + chars[start++] - '0'; if (res > Integer.MAX_VALUE) { break; } } else { break; } } if (flag) { res = -res; } if (res > Integer.MAX_VALUE) { return Integer.MAX_VALUE; } if (res < Integer.MIN_VALUE) { return Integer.MIN_VALUE; } return (int)res; }
9.Palindrome Number
Determine whether an integer is a palindrome. Do this without extra space.
reverse之后看看等不等就可以了
public boolean isPalindrome(int x) { if (x < 0) { return false; } long reverse = 0; int temp = x; while (temp != 0) { reverse = reverse * 10 + temp % 10; temp = temp / 10; } return (int)reverse == x; }
10.Regular Expression Matching
Implement regular expression matching with support for '.' and '*'. '.' Matches any single character. '*' Matches zero or more of the preceding element. The matching should cover the entire input string (not partial). The function prototype should be: bool isMatch(const char *s, const char *p) Some examples: isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "a*") → true isMatch("aa", ".*") → true isMatch("ab", ".*") → true isMatch("aab", "c*a*b") → true
*可以把前边的字符也拿走。
dp[i][j]表示s的前i个字符是否能够与p的前j个字符匹配。
首先初始化s取0个,p的话如果遇到*,就把之前的一个拿走a*b*c*,这样可能匹配。
然后如果遇到字符相等或p遇到'.',那简单。
如果p遇到'*',那么就考虑代表0个1个多个。注意如果p的*的前一个不等于s的当前 ,也不为'.'。那么就是能拿走,代表0个。不然一起处理会带来“*”代表的不是之前字符的问题。
public boolean isMatch(String s, String p) { if (s == null || p == null) { return false; } int m = s.length(); int n = p.length(); char[] sChars = s.toCharArray(); char[] pChars = p.toCharArray(); boolean[][] dp = new boolean[m + 1][n + 1]; // dp[i][j] 表示 s 的前 i 个字符和 p 的前 j 个字符是否能够匹配 dp[0][0] = true; if (n != 0 && pChars[0] == '*') { return false; } for (int j = 2; j <= n; j++) { if (pChars[j - 1] == '*') { dp[0][j] = dp[0][j - 2]; } } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (sChars[i - 1] == pChars[j - 1] || pChars[j - 1] == '.') { dp[i][j] = dp[i - 1][j - 1]; } else if (pChars[j - 1] == '*') { if (pChars[j - 2] == sChars[i - 1] || pChars[j - 2] == '.') { dp[i][j] = dp[i][j - 1] || dp[i][j - 2] || dp[i - 1][j]; } else { dp[i][j] = dp[i][j - 2]; } } } } return dp[m][n]; }
11.Container With Most Water
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. Note: You may not slant the container and n is at least 2.
左右两个指针控制移动,哪边小就移动哪边,因为如果移动另一边的话,这边始终会是一个限制。
public int maxArea(int[] height) { if (height == null || height.length < 2) { return 0; } int left = 0; int right = height.length - 1; int res = 0; while (left < right) { res = Math.max(res, (right - left) * Math.min(height[left], height[right])); if (height[left] < height[right]) { left++; } else { right--; } } return res; }
12.Integer to Roman --- not bug free
Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 to 3999.
变换点为1 4 5 9 10 40 50 90 100...所以特别标注出这些点来,其他的就是累加
// 罗马数字共有七个,即I(1),V(5),X(10),L(50),C(100),D(500),M(1000)。按照下面的规则可以表示任意正整数。 // 重复数次:一个罗马数字重复几次,就表示这个数的几倍。 // 右加左减:在一个较大的罗马数字的右边记上一个较小的罗马数字,表示大数字加小数字。在一个较大的数字的左边记上一个较小的罗马数字,表示大数字减小数字。但是,左减不能跨越等级。比如,99不可以用IC表示,用XCIX表示。 // 加线乘千:在一个罗马数字的上方加上一条横线或者在右下方写M,表示将这个数字乘以1000,即是原数的1000倍。同理,如果上方有两条横线,即是原数的1000000倍。 // 单位限制:同样单位只能出现3次,如40不能表示为XXXX,而要表示为XL。 public String intToRoman(int num) { int[] values={1000,900,500,400,100,90,50,40,10,9,5,4,1}; String[] str={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"}; StringBuilder sb = new StringBuilder(); for (int i = 0; i < values.length; i++) { while (num >= values[i]) { sb.append(str[i]); num -= values[i]; } } return sb.toString(); }
13.Roman to Integer --- not bug free
Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 to 3999.
从后边开始遍历,以是否大于等于5 50 500 为界
public int romanToInt(String s){ if(s==null||s.length()==0){ return 0; } int len=s.length(); int res=0; for(int i=len-1;i>=0;i--){ char cur=s.charAt(i); switch(cur){ case 'I': res+=res>=5?-1:1; break; case 'V': res+=5; break; case 'X': res+=res>=50?-10:10; break; case 'L': res+=50; break; case 'C': res+=res>=500?-100:100; break; case 'D': res+=500; break; case 'M': res+=1000; break; } } return res; }
14.Longest Common Prefix
Write a function to find the longest common prefix string amongst an array of strings.
先找出最短的,然后长度递减依次检测。
public String longestCommonPrefix(String[] strs) { if (strs == null || strs.length == 0) { return ""; } int n = strs.length; String shortest = strs[0]; for (String str : strs) { if (str.length() < shortest.length()) { shortest = str; } } while (shortest.length() > 0) { int i = 0; for (; i < n; i++) { if (strs[i].indexOf(shortest) != 0) { shortest = shortest.substring(0, shortest.length() - 1); break; } } if (i == n) { return shortest; } } return ""; }
上述方法在一个不满足的时候又重头开始检测,其实没这个必要,只要检测后边的就行了。注意一下
public String longestCommonPrefix(String[] strs) { if (strs == null || strs.length == 0) { return ""; } String shortest = strs[0]; int n = strs.length; int i = 0; while (i < n) { while (i < n && strs[i].indexOf(shortest) == 0) { i++; } if (i != n) { shortest = shortest.substring(0, shortest.length() - 1); } } return shortest; }
15.3Sum --- not bug free
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
排序之后两个指针控制移动。需要注意的是:找到一个满足条件之后,left right 的移动规则,为了避免重复是应该放在一个循环中的。
public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if (nums == null || nums.length < 3) { return res; } Arrays.sort(nums); int n = nums.length; for (int i = 0; i < n; i++) { if (i != 0 && nums[i] == nums[i - 1]) { continue; } int left = i + 1; int right = n - 1; while (left < right) { int sum = nums[left] + nums[right] + nums[i]; if (sum == 0) { List<Integer> cur = new ArrayList<Integer>(); cur.add(nums[i]); cur.add(nums[left]); cur.add(nums[right]); res.add(cur); int temp1 = nums[left]; int temp2 = nums[right]; while (left < right && nums[left] == temp1) { left++; } while (left < right && nums[right] == temp2) { right--; } } else if (sum < 0) { left++; } else { right--; } } } return res; }
16.3Sum Closest
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution. For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
和上题大同小异
public int threeSumClosest(int[] nums, int target) { if (nums == null || nums.length < 3) { return Integer.MIN_VALUE; } Arrays.sort(nums); int n = nums.length; int res = nums[0] + nums[1] + nums[2]; for (int i = 0; i < n; i++) { if (i != 0 && nums[i] == nums[i - 1]) { continue; } int left = i + 1; int right = n - 1; while (left < right) { int sum = nums[i] + nums[left] + nums[right]; if (sum == target) { return target; } else if (sum < target) { left++; if (Math.abs(res - target) > target - sum) { res = sum; } } else { right--; if (Math.abs(res - target) > sum - target) { res = sum; } } } } return res; }
17.Letter Combinations of a Phone Number
Given a digit string, return all possible letter combinations that the number could represent. A mapping of digit to letters (just like on the telephone buttons) is given below. Input:Digit string "23" Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
DFS
public List<String> letterCombinations(String digits) { List<String> res = new ArrayList<String>(); if (digits == null || digits.length() == 0) { return res; } char[][] base = {{},{},{'a', 'b', 'c'},{'d', 'e', 'f'},{'g', 'h', 'i'},{'j', 'k', 'l'},{'m', 'n', 'o'}, {'p', 'q', 'r', 's'},{'t', 'u', 'v'},{'w', 'x', 'y', 'z'}}; dfs(digits.toCharArray(), base, res, new char[digits.length()], 0); return res; } public void dfs(char[] chars, char[][] base, List<String> res, char[] strChars, int index) { if (index == chars.length) { res.add(new String(strChars)); return; } for (char c : base[chars[index] - '0']) { strChars[index] = c; dfs(chars, base, res, strChars, index + 1); } }
18.4Sum
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
4sum -> 3sum ->2sum
1 public List<List<Integer>> fourSum(int[] nums, int target) { 2 List<List<Integer>> res = new ArrayList<List<Integer>>(); 3 if (nums == null || nums.length < 4) { 4 return res; 5 } 6 Arrays.sort(nums); 7 int n = nums.length; 8 for (int i = 0; i < n - 3; i++) { 9 if (i != 0 && nums[i] == nums[i - 1]) { 10 continue; 11 } 12 List<Integer> cur = new ArrayList<Integer>(); 13 cur.add(nums[i]); 14 threeSum(nums, target - nums[i], i + 1, res, cur); 15 cur.remove(cur.size() - 1); 16 } 17 return res; 18 } 19 public void threeSum(int[] nums, int target, int index, List<List<Integer>> res, List<Integer> cur) { 20 int n = nums.length; 21 for (int i = index; i < n - 2; i++) { 22 if (i != index && nums[i] == nums[i - 1]) { 23 continue; 24 } 25 cur.add(nums[i]); 26 twoSum(nums, target - nums[i], i + 1, res, cur); 27 cur.remove(cur.size() - 1); 28 } 29 } 30 public void twoSum(int[] nums, int target, int index, List<List<Integer>> res, List<Integer> cur) { 31 int n = nums.length; 32 int left = index; 33 int right = n - 1; 34 while (left < right) { 35 int sum = nums[left] + nums[right]; 36 if (sum < target) { 37 left++; 38 } else if (sum > target) { 39 right--; 40 } else { 41 cur.add(nums[left]); 42 cur.add(nums[right]); 43 res.add(new ArrayList<Integer>(cur)); 44 cur.remove(cur.size() - 1); 45 cur.remove(cur.size() - 1); 46 int temp1 = nums[left]; 47 int temp2 = nums[right]; 48 while (left < right && nums[left] == temp1) { 49 left++; 50 } 51 while (left < right && nums[right] == temp2) { 52 right--; 53 } 54 } 55 } 56 }
19. Remove Nth Node From End of List
Given a linked list, remove the nth node from the end of list and return its head. For example, Given linked list: 1->2->3->4->5, and n = 2. After removing the second node from the end, the linked list becomes 1->2->3->5.
两个指针控制,找到倒数第n个节点的上一个节点。注意k大于结点总数的处理。
public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummyHead = new ListNode(0); dummyHead.next = head; ListNode p1 = dummyHead; ListNode p2 = dummyHead; for (int i = 0; i < n; i++) { p1 = p1.next == null ? head : p1.next; } while (p1.next != null) { p1 = p1.next; p2 = p2.next; } p2.next = p2.next.next; return dummyHead.next; }
20.Valid Parentheses
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.
Stack
1 public boolean isValid(String s) { 2 if (s == null || s.length() == 0) { 3 return false; 4 } 5 char[] chars = s.toCharArray(); 6 Stack<Character> stack = new Stack<Character>(); 7 for (char c : chars) { 8 if (c == '(' || c == '[' || c == '{') { 9 stack.push(c); 10 } else { 11 if (stack.isEmpty()) { 12 return false; 13 } 14 char top = stack.peek(); 15 if (top == '[' && c == ']' || top == '(' && c == ')' || top == '{' && c == '}') { 16 stack.pop(); 17 } else { 18 return false; 19 } 20 } 21 } 22 return stack.isEmpty(); 23 }
21.Merge Two Sorted Lists
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
dummyHead tail, l1 l2往后移动
def mergeTwoLists(self, l1, l2): """ :type l1: ListNode :type l2: ListNode :rtype: ListNode """ if not l1: return l2 if not l2: return l1 dummyHead = ListNode(0) tail = dummyHead while (l1 or l2): if (not l1): tail.next = l2 break if (not l2): tail.next = l1 break if (l1.val < l2.val): tail.next = l1 tail = l1 l1 = l1.next else: tail.next = l2 tail = l2 l2 = l2.next return dummyHead.next
22.Generate Parentheses
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. For example, given n = 3, a solution set is: [ "((()))", "(()())", "(())()", "()(())", "()()()" ]
dp。dp[i]表示i个括号的组合方式。i个括号组合方式的生成就是在i-1个括号上加一个括号,这个括号内部可以包含0,1,...i-1个括号。
public List<String> generateParenthesis(int n) { List<String>[] dp = new ArrayList[n + 1]; // dp[i]表示i个括号的所有可能组合 dp[0] = new ArrayList<String>(); dp[0].add(""); for (int i = 1; i <= n; i++) { dp[i] = new ArrayList<String>(); for (int j = 0; j < i; j++) { for (String inner : dp[j]) { StringBuilder sb = new StringBuilder(); sb.append("("); sb.append(inner); sb.append(")"); int len = sb.length(); for (String outter : dp[i - j - 1]) { sb.append(outter); dp[i].add(sb.toString()); sb.setLength(len); } } } } return dp[n]; }
23.Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
分治。klogn 另外还可以使用优先队列 两两合并
public ListNode mergeKLists(ListNode[] lists) { if (lists == null || lists.length == 0) { return null; } return mergeHelper(lists, 0, lists.length - 1); } public ListNode mergeHelper(ListNode[] lists, int start, int end) { if (start == end) { return lists[start]; } if (start + 1 == end) { return mergeTwo(lists[start], lists[end]); } int mid = start + (end - start) / 2; return mergeTwo(mergeHelper(lists, start, mid), mergeHelper(lists, mid + 1, end)); } public ListNode mergeTwo(ListNode l1, ListNode l2) { ListNode dummyHead = new ListNode(0); ListNode tail = dummyHead; while (l1 != null || l2 != null) { if (l1 == null) { tail.next = l2; break; } if (l2 == null) { tail.next = l1; break; } if (l1.val < l2.val) { tail.next = l1; tail = l1; l1 = l1.next; } else { tail.next = l2; tail = l2; l2 = l2.next; } } return dummyHead.next; }
24.Swap Nodes in Pairs
Given a linked list, swap every two adjacent nodes and return its head. For example, Given 1->2->3->4, you should return the list as 2->1->4->3. Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.
搞清逻辑就行了。
public ListNode swapPairs(ListNode head) { if (head == null || head.next == null) { return head; } ListNode dummyHead = new ListNode(0); dummyHead.next = head; ListNode tail = dummyHead; ListNode cur = head; while (cur != null && cur.next != null) { ListNode swapNode = cur.next; ListNode temp = swapNode.next; tail.next = swapNode; swapNode.next = cur; cur.next = temp; tail = cur; cur = temp; } return dummyHead.next; }
25.Reverse Nodes in k-Group --- not bug free
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is. You may not alter the values in the nodes, only nodes itself may be changed. Only constant memory is allowed. For example, Given this linked list: 1->2->3->4->5 For k = 2, you should return: 2->1->4->3->5 For k = 3, you should return: 3->2->1->4->5
递归。找出前k个之后,后边的分下去做。我对这前k个逆序之后连接上后边的。
public ListNode reverseKGroup(ListNode head, int k) { if (k == 1) { return head; } int count = 0; ListNode cur = head; while (cur != null && count != k) { cur = cur.next; count++; } if (count == k) { ListNode prev = reverseKGroup(cur, k); while (head != cur) { ListNode temp = head.next; head.next = prev; prev = head; head = temp; } return prev; } return head; }
非递归。也是一段一段的找。
public ListNode reverseKGroup(ListNode head, int k) { if (k == 1) { return head; } ListNode cur = head; ListNode dummyHead = new ListNode(0); dummyHead.next = head; ListNode tail = dummyHead; while (cur != null) { int count = 0; while (cur != null && count != k) { cur = cur.next; count++; } if (count == k) { ListNode prev = cur; while (head != cur) { ListNode temp = head.next; head.next = prev; prev = head; head = temp; } ListNode tempNext = tail.next; tail.next = prev; tail = tempNext; } } return dummyHead.next; }
26.Remove Duplicates from Sorted Array
Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length. Do not allocate extra space for another array, you must do this in place with constant memory. For example, Given input array nums = [1,1,2], Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. It doesn't matter what you leave beyond the new length.
two point.
public int removeDuplicates(int[] nums) { if (nums == null || nums.length == 0) { return 0; } int left = 0; int right = 1; int n = nums.length; while (right < n) { if (nums[right] != nums[left]) { swap(nums, ++left, right++); } else { right++; } } return left + 1; } public void swap(int[] nums, int left, int right) { int temp = nums[left]; nums[left] = nums[right]; nums[right] = temp; }
27.Remove Element
Given an array and a value, remove all instances of that value in place and return the new length. Do not allocate extra space for another array, you must do this in place with constant memory. The order of elements can be changed. It doesn't matter what you leave beyond the new length. Example: Given input array nums = [3,2,2,3], val = 3 Your function should return length = 2, with the first two elements of nums being 2.
two point.
public int removeElement(int[] nums, int val) { if (nums == null || nums.length == 0) { return 0; } int left = 0; int n = nums.length; int right = 0; while (right < n) { if (nums[right] != val) { swap(nums, left++, right++); } else { right++; } } return left; } public void swap(int[] nums, int left, int right) { int temp = nums[left]; nums[left] = nums[right]; nums[right] = temp; }
28.Implement strStr()
Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
就是分别检测每个点起始的这个子串可不可以。
public int strStr(String haystack, String needle) { if (haystack == null || needle == null || haystack.length() < needle.length()) { return -1; } char[] chars1 = haystack.toCharArray(); char[] chars2 = needle.toCharArray(); int n1 = haystack.length(); int n2 = needle.length(); for (int i = 0; i + n2 <= n1; i++) { int j = 0; for (; j < n2; j++) { if (chars1[i + j] != chars2[j]) { break; } } if (j == n2) { return i; } } return -1; }
hash,只有hash值相等的时候才比较。O(n)
public static final int BASE = 1000000; public int strStr(String haystack, String needle) { if (haystack == null || needle == null) { return -1; } if (needle.length() == 0) { return 0; } int hLen = haystack.length(); int nLen = needle.length(); int pow = 1; int targetCode = 0; char[] nChars = needle.toCharArray(); for (int i = 0; i < nLen; i++) { if (i < nLen - 1) { pow = (pow * 31) % BASE; } targetCode = (targetCode * 31 + nChars[i]) % BASE; } int hashCode = 0; char[] hChars = haystack.toCharArray(); for (int i = 0; i < hLen; i++) { hashCode = (hashCode * 31 + hChars[i]) % BASE; if (i < nLen - 1) { continue; } if (targetCode == hashCode) { if (haystack.substring(i - nLen + 1, i + 1).equals(needle)) { return i - nLen + 1; } } else { hashCode = (hashCode - pow * hChars[i - nLen + 1]) % BASE; if (hashCode < 0) { hashCode += BASE; } } } return -1; }
29.Divide Two Integers
Divide two integers without using multiplication, division and mod operator. If it is overflow, return MAX_INT.
二分。
public int divide(int dividend, int divisor) { if (divisor == 0) { return -1; } if (dividend == 0) { return 0; } long longdividend = (long)dividend; long longdivisor = (long)divisor; int count = 0; if (longdividend < 0) { longdividend = -longdividend; count++; } if (longdivisor < 0) { longdivisor = -longdivisor; count++; } long res = 0; while (longdividend >= longdivisor) { long base = longdivisor; long num = 1; while (longdividend >= base) { res += num; longdividend -= base; base += base; num += num; } } if(count % 2 != 0) { res = -res; } return res > Integer.MAX_VALUE ? Integer.MAX_VALUE : res < Integer.MIN_VALUE ? Integer.MIN_VALUE : (int)res; }
30.Substring with Concatenation of All Words
You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters. For example, given: s: "barfoothefoobarman" words: ["foo", "bar"]
两层循环,外层循环为wordLen。内存一次取出长度为wordLen的子串,如果不在map中,表明不满足,移动到下一位;在里面的话,还有可能出现次数多了的问题。
public List<Integer> findSubstring(String s, String[] words) { List<Integer> res = new ArrayList<Integer>(); if (res == null || words == null || s.length() == 0 || words.length == 0) { return res; } int sLen = s.length(); int wordLen = words[0].length(); int m = words.length; int winLen = wordLen * m; if (sLen < winLen) { return res; } HashMap<String, Integer> map = new HashMap<String, Integer>(); for (String word : words) { map.put(word, map.getOrDefault(word, 0) + 1); } for (int i = 0; i < wordLen; i++) { int start = i; int j = i; int count = 0; HashMap<String, Integer> timesMap = new HashMap<String, Integer>(); while (j + wordLen <= sLen) { if (start + winLen > sLen) { break; } String str = s.substring(j, j + wordLen); if (!map.containsKey(str)) { j += wordLen; start = j; timesMap.clear(); count = 0; continue; } else { timesMap.put(str, timesMap.getOrDefault(str, 0) + 1); count++; while (timesMap.get(str) > map.get(str)) { String temp = s.substring(start, start + wordLen); timesMap.put(temp, timesMap.get(temp) - 1); start += wordLen; count--; } if (count == m) { res.add(start); String temp = s.substring(start, start + wordLen); timesMap.put(temp, timesMap.get(temp) - 1); start += wordLen; count--; } j += wordLen; // 容易忘记 } } } return res; }
31.Next Permutation --- not bug free
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order). The replacement must be in-place, do not allocate extra memory. Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column. 1,2,3 → 1,3,2 3,2,1 → 1,2,3 1,1,5 → 1,5,1
找到第一个左边比我小的,然后右半部分逆序。如果654321直接返回。不是的话,右半部分找到第一个 49876 比4大的,交换。
public void nextPermutation(int[] nums) { if (nums == null || nums.length < 2) { return; } int n = nums.length; int right = n - 1; while (right > 0 && nums[right] <= nums[right - 1]) { right--; } reverse(nums, right, n - 1); if (right != 0) { int index = findFirstBigger(nums, right, n - 1, nums[right - 1]); int temp = nums[right - 1]; nums[right - 1] = nums[index]; nums[index] = temp; } } public void reverse(int[] nums, int left, int right) { while (left < right) { int temp = nums[left]; nums[left] = nums[right]; nums[right] = temp; left++; right--; } } public int findFirstBigger(int[] nums, int start, int end, int target) { while (start + 1 < end) { int mid = start + (end - start) / 2; if (nums[mid] <= target) { start = mid; } else { end = mid; } } if (nums[start] > target) { return start; } else { return end; } }
32.Longest Valid Parentheses --- not bug free
Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring. For "(()", the longest valid parentheses substring is "()", which has length = 2. Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.
主要是思想,实现很简单。动规:dp[i]表示以i结尾的有效括号串的长度。
public class Solution { public int longestValidParentheses(String s) { if (s == null || s.length() == 0) { return 0; } char[] chars = s.toCharArray(); int n = s.length(); int[] dp = new int[n]; // dp[i]表示以i结尾的最长有效串长度 int res = 0; for (int i = 1; i < n; i++) { if (chars[i] == '(') { continue; } else { if (i- dp[i - 1] - 1 >= 0 && chars[i - dp[i - 1] - 1] == '(') { dp[i] = dp[i - 1] + 2 + ((i - dp[i - 1] - 2 >= 0) ? dp[i - dp[i - 1] - 2] : 0); res = Math.max(res, dp[i]); } } } return res; } }
33.Search in Rotated Sorted Array
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). You are given a target value to search. If found in the array return its index, otherwise return -1. You may assume no duplicate exists in the array.
根据nums[left]与nums[mid]大小关系分段,然后再看target在不在区间上。
public int search(int[] nums, int target) { if (nums == null || nums.length == 0) { return -1; } int left = 0; int right = nums.length - 1; while (left + 1 < right) { int mid = left + (right - left) / 2; if (nums[left] < nums[mid]) { if (nums[left] <= target && target <= nums[mid]) { right = mid; } else { left = mid; } } else { if (nums[mid] <= target && target <= nums[right]) { left = mid; } else { right = mid; } } } if (nums[left] == target) { return left; } if (nums[right] == target) { return right; } return -1; }
34.Search for a Range
Given an array of integers sorted in ascending order, find the starting and ending position of a given target value. Your algorithm's runtime complexity must be in the order of O(log n). If the target is not found in the array, return [-1, -1]. For example, Given [5, 7, 7, 8, 8, 10] and target value 8, return [3, 4].
找第一个和最后一个相等的位置。
def searchRange(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[int] """ if not nums or len(nums) == 0: return [-1, -1] left = self.findFirstEqual(nums, target) if (left == -1): return [-1, -1] right = self.findFinalEqual(nums, target) return [left, right] def findFirstEqual(self, nums, target): left = 0; right = len(nums) - 1 while (left + 1 < right): mid = left + (right - left) / 2 if (nums[mid] < target): left = mid else: right = mid if nums[left] == target: return left elif nums[right] == target: return right else: return -1 def findFinalEqual(self, nums, target): left = 0; right = len(nums) - 1 while (left + 1 < right): mid = left + (right - left) / 2 if (nums[mid] <= target): left = mid else: right = mid if nums[right] == target: return right elif nums[left] == target: return left else: return -1
35.Search Insert Position
Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. You may assume no duplicates in the array. Here are few examples. [1,3,5,6], 5 → 2 [1,3,5,6], 2 → 1 [1,3,5,6], 7 → 4 [1,3,5,6], 0 → 0
找到第一个大于等于的位置。
def searchInsert(self, nums, target): """ :type nums: List[int] :type target: int :rtype: int """ if not nums or len(nums) == 0: return -1 return self.findFirstBiggerOrEqual(nums, target) def findFirstBiggerOrEqual(self, nums, target): start = 0 end = len(nums) - 1 while (start + 1 < end): mid = start + (end - start) / 2 if (nums[mid] < target): start = mid else: end = mid if nums[start] >= target: return start elif nums[end] >= target: return end else: return len(nums)
36.Valid Sudoku --- not bug free
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be partially filled, where empty cells are filled with the character '.'.
依次检测每行每列 小方块。用一个统一的接口来进行检测。
public boolean isValidSudoku(char[][] board) { if (board == null || board.length != 9) { return false; } for (int i = 0; i < 9; i++) { if (!isParticallyValid(board, i, i, 0, 8)) { return false; } if (!isParticallyValid(board, 0, 8, i, i)) { return false; } } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (!isParticallyValid(board, 3 * i, 3 * i + 2, 3 * j, 3 * j + 2)) { return false; } } } return true; } public boolean isParticallyValid(char[][] board, int row_begin, int row_end, int col_begin, int col_end) { HashSet<Character> set = new HashSet<Character>(); for (int i = row_begin; i <= row_end; i++) { for (int j = col_begin; j <= col_end; j++) { if (board[i][j] == '.') { continue; } else { if (!set.add(board[i][j])) { return false; } } } } return true; }
37.Sudoku Solver --- not bug free
Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by the character '.'. You may assume that there will be only one unique solution.
递归程序控制行,然后内部控制列。遇到 '.' 检测合适的char,填入之后深搜下去看看行不,不行的话下一个,都不行的话返回false
public void solveSudoku(char[][] board) { if (board == null || board.length != 9) { return; } solve(board, 0); } public boolean solve(char[][] board, int row_begin) { for (int i = row_begin; i < 9; i++) { for (int j = 0; j < 9; j++) { if (board[i][j] == '.') { for (char c = '1'; c <= '9'; c++) { if (isValid(board, i, j, c)) { board[i][j] = c; if (solve(board, i)) { return true; } board[i][j] = '.'; } } return false; } } } return true; } public boolean isValid(char[][] board, int row, int col, char c) { for (int j = 0; j < 9; j++) { if (board[row][j] == c) { return false; } } for (int i = 0; i < 9; i++) { if (board[i][col] == c) { return false; } } for (int i = row / 3 * 3; i <= row / 3 * 3 + 2; i++) { for (int j = col / 3 * 3; j < col / 3 * 3+ 2; j++) { if (board[i][j] == c) { return false; } } } return true; }
38.Count and Say
The count-and-say sequence is the sequence of integers beginning as follows: 1, 11, 21, 1211, 111221, ... 1 is read off as "one 1" or 11. 11 is read off as "two 1s" or 21. 21 is read off as "one 2, then one 1" or 1211. Given an integer n, generate the nth sequence. Note: The sequence of integers will be represented as a string.
就是按照规则来,一个一个的迭代。注意迭代过程中n--
public String countAndSay(int n) { String res = "1"; while (n > 1) { char[] chars = res.toCharArray(); StringBuilder sb = new StringBuilder(); int start = 0; int i = 0; int m = chars.length; while (i < m) { while (i < m && chars[i] == chars[start]) { i++; } int count = i - start; sb.append(count); sb.append(chars[start]); start = i; } res = sb.toString(); n--; } return res; }
39.Combination Sum
Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. The same repeated number may be chosen from C unlimited number of times.
DFS
public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if (candidates == null || candidates.length == 0) { return res; } Arrays.sort(candidates); DFS(candidates, target, res, new ArrayList<Integer>(), 0); return res; } public void DFS(int[] candidates, int target, List<List<Integer>> res, List<Integer> cur, int index) { if (target == 0) { res.add(new ArrayList<Integer>(cur)); return; } int n = candidates.length; for (int i = index; i < n; i++) { if (candidates[i] > target) { return; } cur.add(candidates[i]); DFS(candidates, target - candidates[i], res, cur, i); cur.remove(cur.size() - 1); } }
40.Combination Sum II
Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. Each number in C may only be used once in the combination.
DFS
public List<List<Integer>> combinationSum2(int[] candidates, int target) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if (candidates == null || candidates.length == 0) { return res; } Arrays.sort(candidates); DFS(candidates, target, res, new ArrayList<Integer>(), 0); return res; } public void DFS(int[] candidates, int target, List<List<Integer>> res, List<Integer> cur, int index) { if (target == 0) { res.add(new ArrayList<Integer>(cur)); return; } int n = candidates.length; for (int i = index; i < n; i++) { if (i != index && candidates[i] == candidates[i - 1]) { continue; } if (candidates[i] > target) { return; } cur.add(candidates[i]); DFS(candidates, target - candidates[i], res, cur, i + 1); cur.remove(cur.size() - 1); } }
41.First Missing Positive
Given an unsorted integer array, find the first missing positive integer. For example, Given [1,2,0] return 3, and [3,4,-1,1] return 2. Your algorithm should run in O(n) time and uses constant space.
实现很简单,主要是思想:可能的结果为1..n + 1,我们把nums[i]放到 i + 1 位置,然后遍历数组,检测nums[i]是否等于 i + 1。
交换的时候,如果遇到小于1的或者大于n的,或者位置上已经满足nums[i] = i + 1的就不用管。其他的如果换过去那个位置也满足条件了,也不用换,否则交换。
public int firstMissingPositive(int[] nums) { if (nums == null || nums.length == 0) { return 1; } int n = nums.length; for (int i = 0; i < n; i++) { if (nums[i] == i + 1 || nums[i] > n || nums[i] < 1) { continue; } else if (nums[nums[i] - 1] != nums[i]){ int temp = nums[nums[i] - 1]; nums[nums[i] - 1] = nums[i]; nums[i] = temp; i--; } } for (int i = 0; i < n; i++) { if (nums[i] != i + 1) { return i + 1; } } return n + 1; }
42.Trapping Rain Water
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining. For example, Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.
找到最大后,最有两边分别求。有了最大就有了保障。
public int trap(int[] height) { if (height == null || height.length == 0) { return 0; } int maxIndex = 0; int max = height[0]; int n = height.length; for (int i = 1; i < n; i++) { if (height[i] > max) { max = height[i]; maxIndex = i; } } int res = 0; int left = 0; for (int i = 1; i < maxIndex; i++) { if (height[i] < height[left]) { res += (height[left] - height[i]); } else { left = i; } } int right = n - 1; for (int i = right - 1; i > maxIndex; i--) { if (height[i] < height[right]) { res += (height[right] - height[i]); } else { right = i; } } return res; }
43.Multiply Strings --- not bug free
Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2. Note: The length of both num1 and num2 is < 110. Both num1 and num2 contains only digits 0-9. Both num1 and num2 does not contain any leading zero. You must not use any built-in BigInteger library or convert the inputs to integer directly.
因子 1 的第 i 位与因子 2 的第 j 位对乘积的影响是第 i + j 和第 i + j + 1 位,所以从后往前一位一位相乘。
public String multiply(String num1, String num2) { if (num1 == null || num1.length() == 0) { return num2; } if (num2 == null || num2.length() == 0) { return num1; } char[] chars1 = num1.toCharArray(); char[] chars2 = num2.toCharArray(); int m = chars1.length; int n = chars2.length; int[] values = new int[m + n]; for (int i = m - 1; i >= 0; i--) { for (int j = n - 1; j >= 0; j--) { int p1 = i + j; int p2 = i + j + 1; int sum = (chars1[i] - '0') * (chars2[j] - '0') + values[p2]; values[p1] += sum / 10; values[p2] = sum % 10; } } StringBuilder sb = new StringBuilder(); for (int value : values) { if (sb.length() == 0 && value == 0) { continue; } sb.append(value); } return sb.length() ==0 ? "0" : sb.toString(); }
44.Wildcard Matching
Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single character. '*' Matches any sequence of characters (including the empty sequence). The matching should cover the entire input string (not partial). The function prototype should be: bool isMatch(const char *s, const char *p) Some examples: isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "*") → true isMatch("aa", "a*") → true isMatch("ab", "?*") → true isMatch("aab", "c*a*b") → false
一种思路可以求出一个数的0~9倍,然后主要设计两个字符串求和。
另一种思路:dp.
public boolean isMatch(String s, String p) { if (s == null || p == null) { return false; } char[] sChars = s.toCharArray(); char[] pChars = p.toCharArray(); int m = s.length(); int n = p.length(); boolean[][] dp = new boolean[m + 1][n + 1]; // dp[i][j]表示s的前i个字符和p的前j个字符是否匹配 dp[0][0] = true; for(int j = 1; j <= n && pChars[j - 1] == '*'; j++) { dp[0][j] = true; } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (sChars[i - 1] == pChars[j - 1] || pChars[j - 1] == '?') { dp[i][j] = dp[i - 1][j - 1]; } else { if (pChars[j - 1] == '*') { dp[i][j] = dp[i][j - 1] || dp[i - 1][j - 1] || dp[i - 1][j]; } } } } return dp[m][n]; }
45.Jump Game II
Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Your goal is to reach the last index in the minimum number of jumps. For example: Given array A = [2,3,1,1,4] The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)
方法一:dp。dp[i]表示到达第i个的最小步数。TLE
public int jump(int[] nums) { if (nums == null || nums.length == 0) { return 0; } int n = nums.length; int[] dp = new int[n]; // dp[i]表示到达i的最小步数 for (int i = 1; i < n; i++) { dp[i] = Integer.MAX_VALUE; for (int j = 0; j < i; j++) { if (nums[j] + j >= i) { dp[i] = Math.min(dp[i], dp[j] + 1); } } } return dp[n - 1]; }
方法二:贪心 --- not bug free
public int jump(int[] nums) { if (nums == null || nums.length == 0) { return 0; } int edge = 0; // 当前步数可以到达哪儿 int nextReach = nums[0]; // 当前步数加1最多可以的到达哪儿 int step = 0; int n = nums.length; for (int i = 1; i < n; i++) { if (i > edge) { step++; edge = nextReach; if (edge >= n - 1) { return step; } } nextReach = Math.max(nextReach, nums[i] + i); if (nextReach == i) { return Integer.MAX_VALUE; } } return step; }
46.Permutations
Given a collection of distinct numbers, return all possible permutations. For example, [1,2,3] have the following permutations: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
DFS
public List<List<Integer>> permute(int[] nums) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if (nums == null || nums.length == 0) { return res; } int n = nums.length; boolean[] used = new boolean[n]; help(nums ,res, new ArrayList<Integer>(), used); return res; } public void help(int[] nums, List<List<Integer>> res, List<Integer> cur, boolean[] used) { if (cur.size() == nums.length) { res.add(new ArrayList<Integer>(cur)); return; } int n = nums.length; for (int i = 0; i < n; i++) { if (used[i]) { continue; } used[i] = true; cur.add(nums[i]); help(nums, res, cur, used); cur.remove(cur.size() - 1); used[i] = false; } }
47.Permutations II
Given a collection of numbers that might contain duplicates, return all possible unique permutations. For example, [1,1,2] have the following unique permutations: [ [1,1,2], [1,2,1], [2,1,1] ]
DFS.别忘了排序
public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if (nums == null || nums.length == 0) { return res; } int n = nums.length; Arrays.sort(nums); boolean[] used = new boolean[n]; help(nums ,res, new ArrayList<Integer>(), used); return res; } public void help(int[] nums, List<List<Integer>> res, List<Integer> cur, boolean[] used) { if (cur.size() == nums.length) { res.add(new ArrayList<Integer>(cur)); return; } int n = nums.length; for (int i = 0; i < n; i++) { if (used[i]) { continue; } if (i != 0 && nums[i] == nums[i - 1] && !used[i - 1]) { continue; } used[i] = true; cur.add(nums[i]); help(nums, res, cur, used); cur.remove(cur.size() - 1); used[i] = false; } }
48.Rotate Image
You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwise). Follow up: Could you do this in-place?
先对角线旋转,再列调换。
public void rotate(int[][] matrix) { if (matrix == null || matrix.length == 0) { return; } reverse(matrix); exchange(matrix); } public void reverse(int[][] matrix) { int n = matrix.length; for (int i = 0; i < n; i++) { for (int j = 0; j < i; j++) { int temp= matrix[i][j]; matrix[i][j] = matrix[j][i]; matrix[j][i] = temp; } } } public void exchange(int[][] matrix) { int n = matrix.length; int left = 0; int right = n - 1; while (left < right) { for (int i = 0; i < n; i++) { int temp = matrix[i][left]; matrix[i][left] = matrix[i][right]; matrix[i][right] = temp; } left++; right--; } }
49.Group Anagrams
Given an array of strings, group anagrams together. For example, given: ["eat", "tea", "tan", "ate", "nat", "bat"], Return: [ ["ate", "eat","tea"], ["nat","tan"], ["bat"] ]
相同的放在一个map key 下。排序之后判断相同不。
public class Solution { public List<List<String>> groupAnagrams(String[] strs) { if (strs == null || strs.length == 0) { return new ArrayList<List<String>>(); } HashMap<String, List<String>> map = new HashMap<String, List<String>>(); for (String str : strs) { char[] chars = str.toCharArray(); Arrays.sort(chars); String key = new String(chars); if (!map.containsKey(key)) { map.put(key, new ArrayList<String>()); } map.get(key).add(str); } return new ArrayList<List<String>>(map.values()); } }
50.Pow(x, n) --- not bug free
Implement pow(x, n).
二分。注意次方为 -2147483648 的时候简单的变为负处理会有溢出问题。所以需要检测讨论。
public class Solution { public double myPow(double x, int n) { if (n == Integer.MIN_VALUE) { if (Math.abs(Math.abs(x) - 1) < 0.000001) { return 1; } else { return Math.abs(x) > 1 ? 0 : Integer.MAX_VALUE; } } if (n < 0) { return 1.0 / myPow(x, -n); } double res = 1; while (n > 0) { double cur = x; int times = 1; while (n >= times) { res *= cur; n -= times; cur *= cur; times += times; } } return res; } }
上边的检测比较麻烦,直接写为不需要检测的。
public double myPow(double x, int n) { if (n < 0) { return 1 / x * 1 / myPow(x, -(n + 1)); } double res = 1; while (n > 0) { double cur = x; int times = 1; while (n >= times) { res *= cur; n -= times; cur *= cur; times += times; } } return res; }
51.N-Queens
The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
递归程序填充行。列检测,主对角线检测,副对角线检测 填充。
public List<List<String>> solveNQueens(int n) { List<List<String>> res = new ArrayList<List<String>>(); char[] base = new char[n]; Arrays.fill(base, '.'); boolean[] col_used = new boolean[n]; boolean[] diag1_used = new boolean[2 * n]; boolean[] diag2_used = new boolean[2 * n]; help(n, res, new ArrayList<String>(), base, 0, col_used, diag1_used, diag2_used); return res; } public void help(int n, List<List<String>> res, List<String> cur, char[] base, int row, boolean[] col_used, boolean[] diag1_used, boolean[] diag2_used) { if (row == n) { res.add(new ArrayList<String>(cur)); return; } for (int j = 0; j < n; j++) { if (!col_used[j] && !diag1_used[row + j] && !diag2_used[j - row + n - 1]) { col_used[j] = true; diag1_used[row + j] = true; diag2_used[j - row + n - 1] = true; base[j] = 'Q'; cur.add(new String(base)); base[j] = '.'; help(n, res, cur, base, row + 1, col_used, diag1_used, diag2_used); col_used[j] = false; diag1_used[row + j] = false; diag2_used[j - row + n - 1] = false; cur.remove(cur.size() - 1); } } }
52.N-Queens II
Follow up for N-Queens problem. Now, instead outputting board configurations, return the total number of distinct solutions.
同样的道理DFS
public int totalNQueens(int n) { int[] res = new int[1]; boolean[] col_used = new boolean[n]; boolean[] diag1_used = new boolean[2 * n]; boolean[] diag2_used = new boolean[2 * n]; help(n, res, col_used, diag1_used, diag2_used, 0); return res[0]; } public void help(int n, int[] res, boolean[] col_used, boolean[] diag1_used, boolean[] diag2_used, int row) { if (n == row) { res[0]++; return; } for (int j = 0; j < n; j++) { if (!col_used[j] && !diag1_used[row + j] && !diag2_used[j - row + n - 1]) { col_used[j] = true; diag1_used[row + j] = true; diag2_used[j - row + n - 1] = true; help(n, res, col_used, diag1_used, diag2_used, row + 1); col_used[j] = false; diag1_used[row + j] = false; diag2_used[j - row + n - 1] = false; } } }
53.Maximum Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest sum. For example, given the array [-2,1,-3,4,-1,2,1,-5,4], the contiguous subarray [4,-1,2,1] has the largest sum = 6.
前缀和为负则更新为0,遍历一遍实时更新res
public int maxSubArray(int[] nums) { int res = Integer.MIN_VALUE; int cur = 0; for (int num : nums) { if (cur < 0) { cur = 0; } cur += num; res = Math.max(res, cur); } return res; }
54.Spiral Matrix --- not bug free
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order. For example, Given the following matrix: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] You should return [1,2,3,6,9,8,7,4,5].
从外到内,一层一层的添加。row_begin row_end col_begin col_end控制。注意代码中Attention部分。
public List<Integer> spiralOrder(int[][] matrix) { List<Integer> res = new ArrayList<Integer>(); if (matrix == null || matrix.length == 0) { return res; } int m = matrix.length; int n = matrix[0].length; help(matrix, res, 0, m - 1, 0, n - 1); return res; } public void help(int[][] matrix, List<Integer> res, int row_begin, int row_end, int col_begin, int col_end) { if (row_begin > row_end || col_begin > col_end) { return; } for (int j = col_begin; j <= col_end; j++) { res.add(matrix[row_begin][j]); } row_begin++; for (int i = row_begin; i <= row_end; i++) { res.add(matrix[i][col_end]); } col_end--; if (row_begin > row_end) { // Attention! return; } for (int j = col_end; j >= col_begin; j--) { res.add(matrix[row_end][j]); } row_end--; if (col_begin > col_end) { // Attention! return; } for (int i = row_end; i >= row_begin; i--) { res.add(matrix[i][col_begin]); } col_begin++; help(matrix, res, row_begin, row_end, col_begin, col_end); }
55.Jump Game --- not bug free
Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Determine if you are able to reach the last index.
贪心算法。max_reach记录最远可以到达的地方。注意中途不可到达检测的返回(见代码Attention)
public boolean canJump(int[] nums) { if (nums == null || nums.length == 0) { return false; } int max_reach = 0; int n = nums.length; for (int i = 0; i < n; i++) { if (max_reach < i) { // Attention! return false; } max_reach = Math.max(max_reach, nums[i] + i); if (max_reach >= n - 1) { return true; } } return false; }
56.Merge Intervals
Given a collection of intervals, merge all overlapping intervals. For example, Given [1,3],[2,6],[8,10],[15,18], return [1,6],[8,10],[15,18].
方法一:使用stack
public List<Interval> merge(List<Interval> intervals) { LinkedList<Interval> res = new LinkedList<Interval>(); if (intervals == null || intervals.size() == 0) { return res; } Collections.sort(intervals, new Comparator<Interval>() { public int compare(Interval i1, Interval i2) { return i1.start - i2.start; } }); Stack<Interval> stack = new Stack<Interval>(); for (Interval interval : intervals) { if (stack.isEmpty()) { stack.push(interval); } else { if (stack.peek().end < interval.start) { stack.push(interval); } else { Interval top = stack.pop(); stack.push(new Interval(top.start, Math.max(top.end, interval.end))); } } } while (!stack.isEmpty()) { res.addFirst(stack.pop()); } return res; }
方法二:使用stack多余了,直接遍历一遍就可以了。
public List<Interval> merge(List<Interval> intervals) { if (intervals == null || intervals.size() < 2) { return intervals; } Collections.sort(intervals, new Comparator<Interval>() { public int compare(Interval i1, Interval i2) { return i1.start - i2.start; } }); List<Interval> res = new ArrayList<Interval>(); int start = intervals.get(0).start; int end = intervals.get(0).end; for (Interval interval : intervals) { if (interval.start > end) { res.add(new Interval(start, end)); start = interval.start; end = interval.end; } else { end = Math.max(end, interval.end); } } res.add(new Interval(start, end)); return res; }
57.Insert Interval --- not bug free
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). You may assume that the intervals were initially sorted according to their start times.
一种方法当然是直接遍历一遍即可。
另外一种是二分。找到第一个end比新区间左边大于等于的,找到第一个start比新区间右边大于的。
public List<Interval> insert(List<Interval> intervals, Interval newInterval) { List<Interval> res = new ArrayList<Interval>(); if (intervals == null) { return res; } int left = findFirstBiggerOrEqual(intervals, newInterval.start); // 第一个end比新区间左边大于等于的 int right = findFirstBigger(intervals, newInterval.end); // 第一个start比新区间右边大于的 if (left == right) { intervals.add(left, newInterval); return intervals; } else { for (int i = 0; i < left; i++) { res.add(intervals.get(i)); } int start = Math.min(newInterval.start, intervals.get(left).start); int end = Math.max(newInterval.end, intervals.get(right - 1).end); res.add(new Interval(start, end)); for (int i = right; i < intervals.size(); i++) { res.add(intervals.get(i)); } return res; } } public int findFirstBiggerOrEqual(List<Interval> intervals, int target) { if (intervals.size() == 0) { return 0; } int start = 0; int end = intervals.size() - 1; while (start + 1 < end) { int mid = start + (end - start) / 2; if (intervals.get(mid).end < target) { start = mid; } else { end = mid; } } if (intervals.get(start).end >= target) { return start; } else if (intervals.get(end).end >= target) { return end; } else { return intervals.size(); } } public int findFirstBigger(List<Interval> intervals, int target) { if (intervals.size() == 0) { return 0; } int start = 0; int end = intervals.size() - 1; while (start + 1 < end) { int mid = start + (end - start) / 2; if (intervals.get(mid).start <= target) { start = mid; } else { end = mid; } } if (intervals.get(start).start > target) { return start; } else if (intervals.get(end).start > target) { return end; } else { return intervals.size(); } }
58.Length of Last Word
Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string. If the last word does not exist, return 0.
由后往前遍历一遍就可以了
public int lengthOfLastWord(String s) { if (s == null || s.length() == 0) { return 0; } s = s.trim(); char[] chars = s.toCharArray(); int n = chars.length; int res = 0; for (int i = n - 1; i >= 0; i--) { if (chars[i] == ' ') { return res; } res++; } return res; }
59.Spiral Matrix II
Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. For example, Given n = 3, You should return the following matrix: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]
和Spiral Matrix一样的道理。
public int[][] generateMatrix(int n) { int[][] res = new int[n][n]; fill(res, 0, n - 1, 0, n - 1, 1); return res; } public void fill(int[][] res, int row_start, int row_end, int col_start, int col_end, int num) { if (row_start > row_end || col_start > col_end) { return; } for (int j = col_start; j <= col_end; j++) { res[row_start][j] = num++; } row_start++; for (int i = row_start; i <= row_end; i++) { res[i][col_end] = num++; } col_end--; if (row_start > row_end) { return; } for (int j = col_end; j >= col_start; j--) { res[row_end][j] = num++; } row_end--; if (col_start > col_end) { return; } for (int i = row_end; i >= row_start; i--) { res[i][col_start] = num++; } col_start++; fill(res, row_start, row_end, col_start, col_end, num); }
60.Permutation Sequence --- not bug free
The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the permutations in order, We get the following sequence (ie, for n = 3): "123" "132" "213" "231" "312" "321" Given n and k, return the kth permutation sequence.
依次确定每一位上的数字。
1, 2 3 4
2, 1 3 4
3, 1 2 4
4, 1 2 3
k / 阶乘即可确定在哪一堆,即可确定当前数。同理,可以确定所有位上的数。
public String getPermutation(int n, int k) { int[] factors = new int[n + 1]; factors[0] = 1; for (int i = 1; i <= n; i++) { factors[i] = factors[i - 1] * i; } List<Integer> nums = new ArrayList<Integer>(); for (int i = 1; i <= n; i++) { nums.add(i); } StringBuilder sb = new StringBuilder(); k--; for (int i = 1; i <= n; i++) { // 每一轮循环确定第i位数 int index = k / factors[n - i]; sb.append(nums.get(index)); nums.remove(index); k -= index * factors[n - i]; } return sb.toString(); }
61.Rotate List --- not bug free
Given a list, rotate the list to the right by k places, where k is non-negative. For example: Given 1->2->3->4->5->NULL and k = 2, return 4->5->1->2->3->NULL.
首先求出链表长度count,k % count
然后通过指针找到翻转的上一个结点
然后就是一些变换指针的操作
public ListNode rotateRight(ListNode head, int k) { if (head == null) { return head; } ListNode left = head; ListNode right = head; int count = 0; while (right != null) { count++; right = right.next; } k %= count; right = head; for (int i = 0; i < k; i++) { right = right.next; } if (right == left) { return head; } while (right.next != null) { right = right.next; left = left.next; } right.next = head; ListNode temp = left.next; left.next = null; return temp; }
如果长度过长,k较小的话,上述方法效率较低。所以直接在求长度循环中,加入条件,如果节点数已经到达k,则直接结束循环。
public ListNode rotateRight(ListNode head, int k) { if (head == null) { return head; } ListNode left = head; ListNode right = head; int count = 0; while (right != null && count != k) { // 未遍历完,数目已经达到k个也会停止 count++; right = right.next; } if (right == null && count == k) { // 刚好有k个结点 return head; } if (count < k) { k %= count; if (k == 0) { // k的整数倍结点 return head; } right = head; for (int i = 0; i < k; i++) { right = right.next; } } while (right.next != null) { right = right.next; left = left.next; } right.next = head; ListNode temp = left.next; left.next = null; return temp; }
62.Unique Paths
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). How many possible unique paths are there?
方法一:二维DP
public int uniquePaths(int m, int n) { int[][] dp = new int[m][n]; // dp[i][j]表示[0, 0]到达[i, j]的方案数 for (int j = 0; j < n; j++) { dp[0][j] = 1; } for (int i = 1; i < m; i++) { dp[i][0] = 1; } for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; } } return dp[m - 1][n - 1]; }
方法二:滚动数组优化
public int uniquePaths(int m, int n) { int[][] dp = new int[2][n]; for (int j = 0; j < n; j++) { dp[0][j] = 1; } for (int i = 1; i < m; i++) { dp[i % 2][0] = 1; for (int j = 1; j < n; j++) { dp[i % 2][j] = dp[(i - 1) % 2][j] + dp[i % 2][j - 1]; } } return dp[(m - 1) % 2][n - 1]; }
方法三:Math C(m + n - 2, n - 1)
public int uniquePaths(int m, int n) { if (m > n) { int temp = m; m = n; n = temp; } long res = 1; for (int i = 1; i < m; i++) { res = res * (i + n - 1) / i; } return (int)res; }
63.Unique Paths II
Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How many unique paths would there be? An obstacle and empty space is marked as 1 and 0 respectively in the grid. For example, There is one obstacle in the middle of a 3x3 grid as illustrated below. [ [0,0,0], [0,1,0], [0,0,0] ]
一样的道理。只不过数学方法不能使用了
public int uniquePathsWithObstacles(int[][] obstacleGrid) { int m = obstacleGrid.length; int n = obstacleGrid[0].length; int[][] dp = new int[2][n]; for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) { dp[0][j] = 1; } for (int i = 1; i < m; i++) { if (obstacleGrid[i][0] == 0) { dp[i % 2][0] = dp[(i - 1) % 2][0]; } else { dp[i % 2][0] = 0; } for (int j = 1; j < n; j++) { if (obstacleGrid[i][j] == 1) { dp[i % 2][j] = 0; } else { dp[i % 2][j] = dp[(i - 1) % 2][j] + dp[i % 2][j - 1]; } } } return dp[(m - 1) % 2][n - 1]; }
64.Minimum Path Sum
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. Note: You can only move either down or right at any point in time.
同理DP
public int minPathSum(int[][] grid) { int m = grid.length; int n = grid[0].length; int[][] dp = new int[m][n]; dp[0][0] = grid[0][0]; for (int j = 1; j < n; j++) { dp[0][j] = dp[0][j - 1] + grid[0][j]; } for (int i = 1; i < m; i++) { dp[i][0] = dp[i - 1][0] + grid[i][0]; } for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j]; } } return dp[m - 1][n - 1]; }
65.Valid Number
Validate if a given string is numeric. Some examples: "0" => true " 0.1 " => true "abc" => false "1 a" => false "2e10" => true Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.
可能出现的字符有 数字 . e + -
必须有数字出现
e前边必须有数字 e后边必须有数字 e只能出现一次
.前边不能有e .只能出现一次
+ -只能出现在开头或者e后边
public boolean isNumber(String s) { if (s == null) { return false; } s = s.trim(); char[] chars = s.toCharArray(); boolean numSeen = false; boolean numAfterE = false; boolean eSeen = false; boolean dotSeen = false; int n = s.length(); for (int i = 0; i < n; i++) { char c = chars[i]; if (Character.isDigit(c)) { numSeen = true; numAfterE = true; } else if (c == 'e') { if (eSeen || !numSeen) { return false; } eSeen = true; numAfterE = false; } else if (c == '.'){ if (eSeen || dotSeen) { return false; } dotSeen = true; } else if (c == '+' || c == '-') { if (i != 0 && chars[i - 1] != 'e') { return false; } } else { return false; } } return numSeen && numAfterE; }
66.Plus One
Given a non-negative integer represented as a non-empty array of digits, plus one to the integer. You may assume the integer do not contain any leading zero, except the number 0 itself. The digits are stored such that the most significant digit is at the head of the list.
直接从后往前 carry携带进位就可以了
def plusOne(self, digits): """ :type digits: List[int] :rtype: List[int] """ if not digits: return digits res = [] carry = 1 n = len(digits) - 1 for i in xrange(n, -1, -1): temp = carry + digits[i] res.insert(0, temp % 10) carry = temp / 10 if carry == 1: res.insert(0, 1) return res
直接原数组上操作
def plusOne(self, digits): """ :type digits: List[int] :rtype: List[int] """ if not digits: return digits carry = 1 n = len(digits) - 1 for i in xrange(n, -1, -1): temp = carry + digits[i] digits[i] = temp % 10 carry = temp / 10 if carry == 0: break if carry == 1: digits.insert(0, 1) return digits
67.Add Binary
Given two binary strings, return their sum (also a binary string). For example, a = "11" b = "1" Return "100".
从后开始,当前位为异或,carry当1的个数大于等于2为正
def addBinary(self, a, b): """ :type a: str :type b: str :rtype: str """ if not a: return b if not b: return a m = len(a) - 1 n = len(b) - 1 carry = 0 res = "" while m >= 0 or n >= 0 or carry != 0: oneNum = carry if m >= 0: carry ^= int(a[m]) if a[m] == '1': oneNum += 1 if n >= 0: carry ^= int(b[n]) if b[n] == '1': oneNum += 1 res = str(carry) + res carry = 1 if oneNum >= 2 else 0 m -= 1 n -= 1 return res
68.Text Justification --- not bug free
Given an array of words and a length L, format the text such that each line has exactly L characters and is fully (left and right) justified. You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces ' ' when necessary so that each line has exactly L characters. Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right. For the last line of text, it should be left justified and no extra space is inserted between words. For example, words: ["This", "is", "an", "example", "of", "text", "justification."] L: 16.
遍历原来的字符串数组,prevLen 和 afterLen分别表示不加和加上当前这个单词后的长度。
如果 afterLen <= maxDepth:
如果已经到达最后一个单词,那个直接处理即可
如果没有达到,那么prevLen更新为afterLen,继续下一个
afterLen > maxDepth:
表明当前这个不能连上,所以处理前边的,处理前边时候由于涉及除以(end - start),所以对于一个单词的情况单独处理
def fullJustify(self, words, maxWidth): """ :type words: List[str] :type maxWidth: int :rtype: List[str] """ if not words: return [] res = [] prevLen = 0 afterLen = 0 n = len(words) start = 0 i = 0 while i < n: afterLen = prevLen + len(words[i]) + (0 if prevLen == 0 else 1) if afterLen <= maxWidth: if i == n - 1: # 到达最后一行 cur = "" for j in xrange(start, i): cur += words[j] + " " cur += words[i] cur += " " * (maxWidth - afterLen) res.append(cur) return res else: prevLen = afterLen i += 1 else: end = i - 1 if end - start == 0: # 一个单词占一行 cur = words[start] cur += " " * (maxWidth - prevLen) res.append(cur) else: space_total = maxWidth - prevLen space_one = space_total / (end - start) space_ugly = space_total % (end - start) cur = "" for j in xrange(start, end): if space_ugly > 0: cur = cur + words[j] + " " * (space_one + 2) space_ugly -= 1 else: cur = cur + words[j] + " " * (space_one + 1) cur += words[end] res.append(cur) prevLen = 0 start = i return res
69.Sqrt(x)
Implement int sqrt(int x). Compute and return the square root of x.
二分。
def mySqrt(self, x): """ :type x: int :rtype: int """ start = 0 end = x while start + 1 < end: mid = (start + end) / 2 square = mid * mid if square < x: start = mid elif square > x: end = mid else: return mid if end * end <= x: return end else: return start
70.Climbing Stairs
You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
def climbStairs(self, n): """ :type n: int :rtype: int """ if n == 0: return 1 if n <= 2: return n prevOne = 2 prevTwo = 1 for i in range(2, n): temp = prevOne prevOne = prevOne + prevTwo prevTwo = temp return prevOne
71.Simplify Path
Given an absolute path for a file (Unix-style), simplify it. For example, path = "/home/", => "/home" path = "/a/./b/../../c/", => "/c"
使用stack。'..'弹出; '.' 不处理;'//'和'/'效果一样
def simplifyPath(self, path): """ :type path: str :rtype: str """ if not path: return None strs = path.split("/") # print len(strs) stack = [] for str in strs: if str == '..' and stack: stack.pop() elif str != '..' and str != '.' and str != '': stack.append(str) res = '' for str in stack: res += str + '/' res = '/' + res.strip('/') return res
72.Edit Distance
Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.) You have the following 3 operations permitted on a word: a) Insert a character b) Delete a character c) Replace a character
dp.
def minDistance(self, word1, word2): """ :type word1: str :type word2: str :rtype: int """ if not word1 and not word2: return 0 m = len(word1) n = len(word2) dp = [[0 for i in range(n + 1)] for j in range(m + 1)] for i in range(n + 1): dp[0][i] = i for i in range(m + 1): dp[i][0] = i for i in range(1, m + 1): for j in range(1, n + 1): if word1[i - 1] == word2[j - 1]: dp[i][j] = dp[i - 1][j - 1] else: dp[i][j] = min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]) + 1 return dp[m][n]
73.Set Matrix Zeroes --- not bug free
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. click to show follow up. Follow up: Did you use extra space? A straight forward solution using O(mn) space is probably a bad idea. A simple improvement uses O(m + n) space, but still not the best solution. Could you devise a constant space solution?
用第一行第一列来记录这行这列是否有"0",但是首先需要一个boolean来记录最开始的第一行第一列时候本身就有0。注意代码中Attention部分
def setZeroes(self, matrix): """ :type matrix: List[List[int]] :rtype: void Do not return anything, modify matrix in-place instead. """ if not matrix: return m = len(matrix) n = len(matrix[0]) firstRow = False firstCol = False for j in xrange(n): if matrix[0][j] == 0: firstRow = True break for i in xrange(m): if matrix[i][0] == 0: firstCol = True break for i in xrange(m): for j in xrange(n): if matrix[i][j] == 0: matrix[i][0] = 0 matrix[0][j] = 0 for i in xrange(1, m): # Attention if matrix[i][0] == 0: self.setRowZero(matrix, i) for j in xrange(1, n): # Attention if matrix[0][j] == 0: self.setColZero(matrix, j) if firstRow: self.setRowZero(matrix, 0) if firstCol: self.setColZero(matrix, 0) def setColZero(self, matrix, col): m = len(matrix) for i in range(m): matrix[i][col] = 0 def setRowZero(self, matrix, row): n = len(matrix[0]) for j in range(n): matrix[row][j] = 0
74.Search a 2D Matrix
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties: Integers in each row are sorted from left to right. The first integer of each row is greater than the last integer of the previous row.
二分。
def searchMatrix(self, matrix, target): """ :type matrix: List[List[int]] :type target: int :rtype: bool """ if not matrix: return False m = len(matrix) n = len(matrix[0]) if m == 0 or n == 0: return False start = 0 end = m * n - 1 while start + 1 < end: mid = (start + end) / 2 num = matrix[mid / n][mid % n] if num == target: return True elif num < target: start = mid else: end = mid return matrix[start / n][start % n] == target or matrix[end / n][end % n] == target
75.Sort Colors
Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue. Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
两边两个指针控制,中间index移动。注意的是,左边换过去的时候,index也要+1,如代码Attention所示
def sortColors(self, nums): """ :type nums: List[int] :rtype: void Do not return anything, modify nums in-place instead. """ if not nums: return n = len(nums) left = 0 right = n - 1 index = 0 while index <= right: if nums[index] == 0: temp = nums[left] nums[left] = nums[index] nums[index] = temp left += 1 index += 1 # Attention! elif nums[index] == 2: temp = nums[right] nums[right] = nums[index] nums[index] = temp right -= 1 else: index += 1
76.Minimum Window Substring
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n). For example, S = "ADOBECODEBANC" T = "ABC" Minimum window is "BANC".
和第30题比较接近,区别是这里允许有无关字符的出现。
用一个map记录tLen中字符的出现。然后遍历sLen,二话不说,map对应位置先减,如果减了之后大于等于0,表明这是一个“有用的”,更新count。当count为0的时候,更新结果。并且二话不说先加,如果加完后map[start] > 0,表明这是一个有用的,更新count。
def minWindow(self, s, t): """ :type s: str :type t: str :rtype: str """ if not s or not t: return "" sLen = len(s) tLen = len(t) if sLen < tLen: return "" map = [0] * 128 for c in t: map[ord(c)] += 1 minStart = 0 minEnd = sLen start = 0 count = tLen for i in xrange(sLen): map[ord(s[i])] -= 1 if map[ord(s[i])] >= 0: count -= 1 while count == 0: if i - start < minEnd - minStart: minStart = start minEnd = i map[ord(s[start])] += 1 if map[ord(s[start])] > 0: count += 1 start += 1 if start + tLen > sLen: break if minStart == 0 and minEnd == sLen: return "" else: return s[minStart:minEnd + 1]
77.Combinations
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For example, If n = 4 and k = 2, a solution is: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
注意代码中Attention部分的处理。当剩余的个数加起来达不到k个的时候,就不需要再深搜下去,这可以节约很多时间。否则TLE了
def combine(self, n, k): """ :type n: int :type k: int :rtype: List[List[int]] """ res = [] if n < k: return res self.dfs(n, k, res, [], 1) return res def dfs(self, n, k, res, cur, index): if len(cur) == k: res.append(cur[:]) return for i in xrange(index, n + 1): if (n - i + 1 + len(cur) < k): # Attention! break; cur.append(i) self.dfs(n, k, res, cur, i + 1) cur.pop()
78.Subsets
Given a set of distinct integers, nums, return all possible subsets.
DFS
def subsets(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ res = [] if not nums: return res self.dfs(nums, 0, res, []) return res def dfs(self, nums, index, res, cur): res.append(cur[:]) n = len(nums) for i in xrange(index, n): cur.append(nums[i]) self.dfs(nums, i + 1, res, cur) cur.pop()
79.Word Search
Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.
DFS.
def exist(self, board, word): """ :type board: List[List[str]] :type word: str :rtype: bool """ if not board or not word: return False m = len(board) n = len(board[0]) if m * n < len(word): return False for i in xrange(m): for j in xrange(n): if self.dfs(board, word, i, j, 0): return True; return False def dfs(self, board, word, i, j, index): m = len(board) n = len(board[0]) if index == len(word): return True if i < 0 or i >= m: return False if j < 0 or j >= n: return False if board[i][j] != word[index]: return False temp = board[i][j] board[i][j] = '.' res = self.dfs(board, word, i + 1, j, index + 1) \ or self.dfs(board, word, i - 1, j, index + 1) \ or self.dfs(board, word, i, j + 1, index + 1) \ or self.dfs(board, word, i, j - 1, index + 1) board[i][j] = temp return res
80.Remove Duplicates from Sorted Array II
Follow up for "Remove Duplicates": What if duplicates are allowed at most twice? For example, Given sorted array nums = [1,1,1,2,2,3], Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3. It doesn't matter what you leave beyond the new length.
times记录次数,首先start = 0 times = 1,start位置表示已经满足了。然后遍历数组,如果nums[i] == nums[start] and times >= 2表明不可加进来,否则可以加进来。加进来要看nums[i]和nums[start]的关系控制times的取值变化。然后start + 1后值换过来。
def removeDuplicates(self, nums): """ :type nums: List[int] :rtype: int """ if not nums: return 0 n = len(nums) start = 0 times = 1 for i in xrange(1, n): if nums[i] == nums[start] and times >= 2: continue else: if nums[i] == nums[start]: times += 1 else: times = 1 start += 1 nums[start] = nums[i] return start + 1
81.Search in Rotated Sorted Array II
Follow up for "Search in Rotated Sorted Array": What if duplicates are allowed? Would this affect the run-time complexity? How and why?
允许重复了,那么其实最坏的复杂度就会达到O(n)了。这里首先移动start,让nums[start] != nums[end]是为了保证:如果nums[start] <= nums[mid],那么[start, mid]一定是单增的,然后分段来考虑. 1 3 1 1 1
def search(self, nums, target): """ :type nums: List[int] :type target: int :rtype: bool """ if not nums: return False n = len(nums) start = 0 end = n - 1 while start < end and nums[start] == nums[end]: # 保证start到mid一定是单增的 start += 1 while start + 1 < end: mid = (start + end) / 2 if nums[start] <= nums[mid]: if nums[start] <= target and target <= nums[mid]: end = mid else: start = mid else: if nums[mid] <= target and target <= nums[end]: start = mid else: end = mid return nums[start] == target or nums[end] == target
82.Remove Duplicates from Sorted List II
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. For example, Given 1->2->3->3->4->4->5, return 1->2->5. Given 1->1->1->2->3, return 2->3.
有重复往后走,最后看tail.next是否等于head,等的话表明head位置这个值满足条件,不等的话不满足。
def deleteDuplicates(self, head): """ :type head: ListNode :rtype: ListNode """ if not head: return head dummyHead = ListNode(0) dummyHead.next = head tail = dummyHead while head: while head.next and head.val == head.next.val: head = head.next if tail.next == head: tail = head head = head.next else: head = head.next tail.next = head return dummyHead.next
83.Remove Duplicates from Sorted List
Given a sorted linked list, delete all duplicates such that each element appear only once. For example, Given 1->1->2, return 1->2. Given 1->1->2->3->3, return 1->2->3.
现在允许重复的出现一次就更好办了。如果cur.val == cur.next.val 那么 cur.next = cur.next.next
def deleteDuplicates(self, head): """ :type head: ListNode :rtype: ListNode """ if not head: return head cur = head while cur: tmp = cur.val while cur.next and cur.next.val == tmp: cur.next = cur.next.next cur = cur.next return head
84.Largest Rectangle in Histogram
Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.
方法一:最大直方图面积,递增栈。新来的元素如果大于栈顶元素,那么压入栈,小于等于栈顶元素,表明此时栈顶元素的右边界已经找到,弹出后的新栈顶就是之前栈顶的左边界。注意栈中存储的是下标,最后需要一个统一弹出,计算下标区间长度的时候不包含端点。
def largestRectangleArea(self, heights): """ :type heights: List[int] :rtype: int """ if not heights: return 0 s = [] n = len(heights) res = 0 s.append(-1) for i in xrange(n + 1): cur = (-1 << 31) if i == n else heights[i] if len(s) == 1 or heights[s[-1]] < cur: s.append(i) else: while len(s) > 1 and heights[s[-1]] >= cur: index = s.pop() res = max(res, (i - s[-1] - 1) * heights[index]) s.append(i) return res
方法二:DP.left[i] right[i]分别表示往左边和往右边可以扩展多少
def largestRectangleArea(self, heights): """ :type heights: List[int] :rtype: int """ if not heights: return 0 n = len(heights) left = [0] * n # 高度扩张的最左边 right = [0] * n # 高度扩张的最右边 for i in xrange(1, n): index = i - 1 while index >= 0 and heights[index] >= heights[i]: index = left[index] - 1 left[i] = index + 1 right[-1] = n - 1 res = (right[-1] - left[-1] + 1) * heights[-1] for i in xrange(n - 1, -1, -1): index = i + 1 while index < n and heights[index] >= heights[i]: index = right[index] + 1 right[i] = index - 1 res = max(res, (right[i] - left[i] + 1) * heights[i]) return res
85.Maximal Rectangle
Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area. For example, given the following matrix: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 Return 6.
当然,第一种思路可以考虑以每一行为底的最大矩形,就相当于做了n次的Largest Rectangle in Histogram,用左右扩的方法的话最坏的时间复杂度是O(n * m ^ 2),用递增栈的话最坏的时间复杂度是O(n * m)
这里不直接的转化为一维,而是直接操作。引入一个curLeft记录当前往左扩和当前往右扩,最后时间复杂度优化到O(n * m)
def maximalRectangle(self, matrix): """ :type matrix: List[List[str]] :rtype: int """ if not matrix: return 0 m = len(matrix) n = len(matrix[0]) heights = [0] * n left = [0] * n right = [n] * n res = 0 for i in xrange(m): curLeft = 0 curRight = n for j in xrange(n): if matrix[i][j] == '1': heights[j] += 1 left[j] = max(left[j], curLeft) else: heights[j] = 0 left[j] = 0 curLeft = j + 1 for j in xrange(n - 1, -1, -1): if matrix[i][j] == '1': right[j] = min(right[j], curRight) res = max(res, (right[j] - left[j]) * heights[j]) else: right[j] = n curRight = j return res
86.Partition List
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x. You should preserve the original relative order of the nodes in each of the two partitions. For example, Given 1->4->3->2->5->2 and x = 3, return 1->2->2->4->3->5.
dummySmall
dummyBigger
tailSmall
tailBigger
需要注意的是最后把tailBigger.next = None
def partition(self, head, x): """ :type head: ListNode :type x: int :rtype: ListNode """ if not head: return head dummySmall = ListNode(0) tailSmall = dummySmall dummyBigger = ListNode(0) tailBigger = dummyBigger while head: if head.val < x: tailSmall.next = head tailSmall = head head = head.next else: tailBigger.next = head tailBigger = head head = head.next tailSmall.next = dummyBigger.next tailBigger.next = None #Attention! return dummySmall.next
87.Scramble String
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively. Below is one possible representation of s1 = "great": great / \ gr eat / \ / \ g r e at / \ a t To scramble the string, we may choose any non-leaf node and swap its two children. For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat". rgeat / \ rg eat / \ / \ r g e at / \ a t We say that "rgeat" is a scrambled string of "great". Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae". rgtae / \ rg tae / \ / \ r g ta e / \ t a We say that "rgtae" is a scrambled string of "great". Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.
递归。检测字符出现的是不是一样,然后左右取,左右等去判断
def isScramble(self, s1, s2): """ :type s1: str :type s2: str :rtype: bool """ if s1 == s2: return True if not s1 or not s2: return False m = len(s1) n = len(s2) if m != n: return False map = [0] * 128 for c in s1: map[ord(c)] += 1 for c in s2: if map[ord(c)] == 0: return False map[ord(c)] -= 1 for i in range(1, m): if self.isScramble(s1[i:], s2[i:]) and self.isScramble(s1[:i], s2[:i]): return True if self.isScramble(s1[i:], s2[:n - i]) and self.isScramble(s1[:i], s2[n - i:]): return True return False
88.Merge Sorted Array
Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note: You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1 and nums2 are m and n respectively.
三个指针控制移动即可。
def merge(self, nums1, m, nums2, n): """ :type nums1: List[int] :type m: int :type nums2: List[int] :type n: int :rtype: void Do not return anything, modify nums1 in-place instead. """ index = m + n - 1 m -= 1 n -= 1 while m >= 0 and n >= 0: if nums1[m] > nums2[n]: nums1[index] = nums1[m] m -= 1 index -= 1 else: nums1[index]= nums2[n] n -= 1 index -= 1 while n >= 0: nums1[index] = nums2[n] index -= 1 n -= 1
89.Gray Code
The gray code is a binary numeral system where two successive values differ in only one bit. Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0. For example, given n = 2, return [0,1,3,2]. Its gray code sequence is: 00 - 0 01 - 1 11 - 3 10 - 2
n + 1是n的数,再加上n的数的倒序加上当前增长值
def grayCode(self, n): """ :type n: int :rtype: List[int] """ if n <= 0: return [0] res = [0, 1] temp = 2 for i in xrange(1, n): size = len(res) for j in xrange(size - 1, -1, -1): res.append(res[j] + temp) temp *= 2 return res
90.Subsets II
Given a collection of integers that might contain duplicates, nums, return all possible subsets. Note: The solution set must not contain duplicate subsets. For example, If nums = [1,2,2], a solution is: [ [2], [1], [1,2,2], [2,2], [1,2], [] ]
DFS
def subsetsWithDup(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ res = [] if not nums: return res nums.sort() self.dfs(nums, res, [], 0) return res def dfs(self, nums, res, cur, index): res.append(cur[:]) n = len(nums) for i in xrange(index, n): if i != index and nums[i] == nums[i - 1]: continue cur.append(nums[i]) self.dfs(nums, res, cur, i + 1) cur.pop()
91.Decode Ways --- not nug free
A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given an encoded message containing digits, determine the total number of ways to decode it. For example, Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12). The number of ways decoding "12" is 2.
dp[i]表示必须以i结尾的译码方案数
遍历原字符串,首先以s[i- 1]是否为‘0’划分,为‘0’的很简单;不为‘0’的话,获取前一位结合的数num,分num>26与否,大于26很简单,小于的话,以s[i]是否为‘0’来划分。
def numDecodings(self, s): """ :type s: str :rtype: int """ if not s: return 0 if s[0] == '0': return 0 n = len(s) dp = [0] * n dp[0] = 1 for i in xrange(1, n): if s[i - 1] == '0': if s[i] == '0': return 0 else: dp[i] = dp[i - 1] else: num = int(s[i - 1]) * 10 + int(s[i]) if num > 26: if s[i] == '0': return 0 else: dp[i] = dp[i - 1] else: if s[i] == '0': dp[i] = dp[i - 2] if i >= 2 else 1 else: dp[i] = dp[i - 1] + dp[i - 2] if i >= 2 else 2 return dp[-1]
92.Reverse Linked List II
Reverse a linked list from position m to n. Do it in-place and in one-pass. For example: Given 1->2->3->4->5->NULL, m = 2 and n = 4, return 1->4->3->2->5->NULL. Note: Given m, n satisfy the following condition: 1 ≤ m ≤ n ≤ length of list.
首先找到第m个结点的上一个结点prev,然后prev1.next = 后边的逆序,逆序部分也要和后边接上。
def reverseBetween(self, head, m, n): """ :type head: ListNode :type m: int :type n: int :rtype: ListNode """ if not head: return head dummyHead = ListNode(0) dummyHead.next = head prev1 = dummyHead for i in xrange(1, m): # if not prev1: # return None prev1= prev1.next prev1.next = self.reverse(prev1.next, m, n) return dummyHead.next def reverse(self, head, m, n): temp1 = head prev = None n += 1 for i in xrange(m, n): # if not head: # return None temp = head.next head.next = prev prev = head head = temp temp1.next = head return prev
93.Restore IP Addresses --- not nug free
Given a string containing only digits, restore it by returning all possible valid IP address combinations. For example: Given "25525511135", return ["255.255.11.135", "255.255.111.35"]. (Order does not matter)
backtracking.
start记录ip的这一位的开始点,然后遍历其往后的三为看可不可以构成一个0-255的数,深搜下去。
注意python的 if else 三目运算语句的优先级比算数运算符优先级高。
def restoreIpAddresses(self, s): """ :type s: str :rtype: List[str] """ if not s or len(s) < 4 or len(s) > 12: return [] res = [] self.dfs(s, res, 0, 0, '') return res def dfs(self, s, res, start, count, ip): if count > 4: return if count == 4 and start == len(s): res.append(ip[:]) return for i in xrange(1, 4): if start + i > len(s): break temp = s[start:start + i] if temp[0] == '0' and i != 1: break if i == 3 and int(temp) > 255: break self.dfs(s, res, start + i, count + 1, ip + temp + ('' if count == 3 else '.'))
94.Binary Tree Inorder Traversal
递归:
def inorderTraversal(self, root): """ :type root: TreeNode :rtype: List[int] """ res = [] self.inorderTraverse(root, res) return res def inorderTraverse(self, root, res): if not root: return self.inorderTraverse(root.left, res) res.append(root.val) self.inorderTraverse(root.right, res)
非递归:
def inorderTraversal(self, root): """ :type root: TreeNode :rtype: List[int] """ res = [] if not root: return res stack = [] while stack or root: while root: stack.append(root) root = root.left root = stack.pop() res.append(root.val) root = root.right return res
95.Unique Binary Search Trees II --- not nug free
Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1...n. For example, Given n = 3, your program should return all 5 unique BST's shown below. 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
分治。分治程序求解[start, end]的所有树,可以以这区间的任何一个为根节点,左右分治。注意代码中Attention!
def generateTrees(self, n): """ :type n: int :rtype: List[TreeNode] """ if n < 1: return [] return self.help(1, n) def help(self, start, end): res = [] if start > end: res.append(None) #Attention! return res if start == end: res.append(TreeNode(start)) return res for i in xrange(start, end + 1): left = self.help(start, i - 1) right = self.help(i + 1, end) for l in left: for r in right: root = TreeNode(i) # Attnetion! root.left = l root.right = r res.append(root) return res
dp。方法一中涉及许多重复计算,所以这里使用dp。dp[i]表示[1,i]的所有树
def generateTrees(self, n): """ :type n: int :rtype: List[TreeNode] """ if n < 1: return [] dp = [] dp.append([]) dp[0].append(None) for i in xrange(1, (n + 1)): dp.append([]) for j in xrange(i): left = dp[j] right = dp[i - j - 1] for l in left: for r in right: root = TreeNode(j + 1) root.left = l root.right = self.clone(r, j + 1) dp[i].append(root) return dp[n] def clone(self, root, num): if not root: return None newRoot = TreeNode(root.val + num) newRoot.left = self.clone(root.left, num) newRoot.right = self.clone(root.right, num) return newRoot
96. Unique Binary Search Trees
Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For example, Given n = 3, there are a total of 5 unique BST's. 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
dp.dp[i]表示[1, i]的方案数。
def numTrees(self, n): """ :type n: int :rtype: int """ if n < 1: return 0 dp = [0] * (n + 1) dp[0] = 1 for i in xrange(1, n + 1): for j in xrange(i): dp[i] += dp[j] * dp[i - 1 - j] return dp[n]
97.Interleaving String
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example, Given: s1 = "aabcc", s2 = "dbbca", When s3 = "aadbbcbcac", return true. When s3 = "aadbbbaccc", return false.
dp.dp[i][j]表示s1的前i个字符,s2的前j个字符是否能够与s3的前i + j个字符匹配
def isInterleave(self, s1, s2, s3): """ :type s1: str :type s2: str :type s3: str :rtype: bool """ m = len(s1) n = len(s2) if m + n != len(s3): return False dp = [[False for j in xrange(n + 1)] for i in xrange(m + 1)] # dp[i][j]表示s1的前i个字符,s2的前j个字符是否能够与s3的前i + j个字符匹配 dp[0][0] = True for j in xrange(1, (n + 1)): if s2[j - 1] == s3[j - 1]: dp[0][j] = True else: break for i in xrange(1, (m + 1)): if (s1[i - 1] == s3[i - 1]): dp[i][0] = True else: break for i in xrange(1, (m + 1)): for j in xrange(1, (n + 1)): if s1[i - 1] == s3[i + j - 1]: dp[i][j] |= dp[i - 1][j] if s2[j - 1] == s3[i + j - 1]: dp[i][j] |= dp[i][j - 1] return dp[m][n]
98.Validate Binary Search Tree
Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than the node's key. The right subtree of a node contains only nodes with keys greater than the node's key. Both the left and right subtrees must also be binary search trees. Example 1: 2 / \ 1 3 Binary tree [2,1,3], return true. Example 2: 1 / \ 2 3 Binary tree [1,2,3], return false.
递归。递归程序控制一个最大值和最小值,注意最开始的这个最大值和最小值的初始化问题。
def isValidBST(self, root): """ :type root: TreeNode :rtype: bool """ return self.help(root, (1 << 31), (-1 << 31) - 1) def help(self, root, maxNum, minNum): if not root: return True if minNum < root.val < maxNum: return self.help(root.left, root.val, minNum) and self.help(root.right, maxNum, root.val) else: return False
99.Recover Binary Search Tree
wo elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing its structure. Note: A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?
中序遍历变形。找到prev.val > root.val的。
非递归:
def recoverTree(self, root): """ :type root: TreeNode :rtype: void Do not return anything, modify root in-place instead. """ first = None second = None prev = None stack = [] while stack or root: while root: stack.append(root) root = root.left root = stack.pop() if prev and prev.val > root.val: if first: second = root break else: first = prev second = root prev = root root = root.right if first: temp = first.val first.val = second.val second.val = temp
递归:
first = None second = None prev = None def recoverTree(self, root): """ :type root: TreeNode :rtype: void Do not return anything, modify root in-place instead. """ global first global second self.inorderHelp(root) if self.first: temp = self.first.val self.first.val = self.second.val self.second.val = temp def inorderHelp(self, root): global first global second global prev if not root: return self.inorderHelp(root.left) if self.prev and self.prev.val > root.val: if self.first: self.second = root return else: self.first = self.prev self.second = root self.prev = root self.inorderHelp(root.right)
100.Same Tree
Given two binary trees, write a function to check if they are equal or not. Two binary trees are considered equal if they are structurally identical and the nodes have the same value.
分治。
def isSameTree(self, p, q): """ :type p: TreeNode :type q: TreeNode :rtype: bool """ if not p and not q: return True if not p: return False if not q: return False if p.val != q.val: return False return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
101.Symmetric Tree
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For example, this binary tree [1,2,2,3,4,4,3] is symmetric: 1 / \ 2 2 / \ / \ 3 4 4 3 But the following [1,2,2,null,3,null,3] is not: 1 / \ 2 2 \ \ 3 3
分治。
def isSymmetric(self, root): """ :type root: TreeNode :rtype: bool """ if not root: return True return self.isSame(root.left, root.right) def isSame(self, root1, root2): if not root1 and not root2: return True if not root1 or not root2: return False if root1.val != root2.val: return False return self.isSame(root1.left, root2.right) and self.isSame(root1.right, root2.left)
102.Binary Tree Level Order Traversal
Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). For example: Given binary tree [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 return its level order traversal as: [ [3], [9,20], [15,7] ]
队列。
def levelOrder(self, root): """ :type root: TreeNode :rtype: List[List[int]] """ res = [] if not root: return res queue = [] queue.append(root) while queue: size = len(queue) cur = [] for i in xrange(size): root = queue.pop(0) cur.append(root.val) if root.left: queue.append(root.left) if root.right: queue.append(root.right) res.append(cur[:]) return res
103.Binary Tree Zigzag Level Order Traversal
Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). For example: Given binary tree [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 return its zigzag level order traversal as: [ [3], [20,9], [15,7] ]
Z字形遍历。flag记录。队列
def zigzagLevelOrder(self, root): """ :type root: TreeNode :rtype: List[List[int]] """ res = [] if not root: return res queue = [] queue.append(root) flag = True while queue: size = len(queue) cur = [] for i in xrange(size): root = queue.pop(0) if flag: cur.append(root.val) else: cur.insert(0, root.val) if root.left: queue.append(root.left) if root.right: queue.append(root.right) flag = not flag res.append(cur[:]) return res
104.Maximum Depth of Binary Tree
Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
分治。
def maxDepth(self, root): """ :type root: TreeNode :rtype: int """ if not root: return 0 return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))
105.Construct Binary Tree from Preorder and Inorder Traversal
Given preorder and inorder traversal of a tree, construct the binary tree.
分治。
def buildTree(self, preorder, inorder): """ :type preorder: List[int] :type inorder: List[int] :rtype: TreeNode """ if not preorder or not inorder or not len(preorder) == len(inorder): return None map = {} n = len(preorder) for i in xrange(n): map[inorder[i]] = i return self.help(preorder, inorder, 0, len(preorder) - 1, 0, len(inorder) - 1, map) def help(self, preorder, inorder, prestart, preend, instart, inend, map): if prestart > preend: return None if prestart == preend: return TreeNode(preorder[prestart]) root = TreeNode(preorder[prestart]) index = map[preorder[prestart]] root.left = self.help(preorder, inorder, prestart + 1, index - instart + prestart, instart, index - 1, map) root.right = self.help(preorder, inorder, index - instart + prestart + 1, preend, index + 1, inend, map) return root
106.Construct Binary Tree from Inorder and Postorder Traversal
Given inorder and postorder traversal of a tree, construct the binary tree.
分治。
def buildTree(self, inorder, postorder): """ :type inorder: List[int] :type postorder: List[int] :rtype: TreeNode """ if not inorder or not postorder: return None if len(inorder) != len(postorder): return None map = {} n = len(inorder) for i in xrange(n): map[inorder[i]] = i return self.help(inorder, 0, n - 1, postorder, 0, n - 1, map) def help(self, inorder, instart, inend, postorder, poststart, postend, map): if instart > inend: return None if instart == inend: return TreeNode(inorder[instart]) root = TreeNode(postorder[postend]) index = map[postorder[postend]] root.left = self.help(inorder, instart, index - 1, postorder, poststart, poststart + index - instart - 1, map) root.right = self.help(inorder, index + 1, inend, postorder, poststart + index - instart, postend - 1, map) return root
107.Binary Tree Level Order Traversal II
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root). For example: Given binary tree [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 return its bottom-up level order traversal as: [ [15,7], [9,20], [3] ]
层序遍历。
def levelOrderBottom(self, root): """ :type root: TreeNode :rtype: List[List[int]] """ res = [] if not root: return res queue = [] queue.append(root) while queue: size = len(queue) cur = [] for i in xrange(size): root = queue.pop(0) cur.append(root.val) if root.left: queue.append(root.left) if root.right: queue.append(root.right) res.insert(0, cur[:]) return res
108.Convert Sorted Array to Binary Search Tree
Given an array where elements are sorted in ascending order, convert it to a height balanced BST.
分治。
def sortedArrayToBST(self, nums): """ :type nums: List[int] :rtype: TreeNode """ if not nums: return None return self.help(nums, 0, len(nums) - 1) def help(self, nums, start, end): if start > end: return None if start == end: return TreeNode(nums[start]) mid = (start + end) / 2 root = TreeNode(nums[mid]) root.left = self.help(nums, start, mid - 1) root.right = self.help(nums, mid + 1, end) return root
109.Convert Sorted List to Binary Search Tree --- not bug free
Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
首先求出节点个数,start, end控制递归。外部使用temp控制遍历到哪儿了。
temp = None def sortedListToBST(self, head): """ :type head: ListNode :rtype: TreeNode """ if not head: return None global temp self.temp = head n = 0 cur = head while cur: n += 1 cur = cur.next return self.help(0, n - 1) def help(self, start, end): if start > end: return None if start == end: val = self.temp.val self.temp = self.temp.next return TreeNode(val) mid = (start + end) / 2 global temp left = self.help(start, mid - 1) root = TreeNode(self.temp.val) self.temp = self.temp.next right = self.help(mid + 1, end) root.left = left root.right = right return root
110.Balanced Binary Tree
Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.
分治。-1 表示不平衡。
def isBalanced(self, root): """ :type root: TreeNode :rtype: bool """ if not root: return True return not self.height(root) == -1 def height(self, root): if not root: return 0 left = self.height(root.left) right = self.height(root.right) if left == -1 or right == -1: return -1 if abs(left - right) > 1: return -1 return max(left, right) + 1
111.Minimum Depth of Binary Tree
Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.
层序遍历。
def minDepth(self, root): """ :type root: TreeNode :rtype: int """ if not root: return 0 queue = [] queue.append(root) res = 1 while queue: size = len(queue) for i in xrange(size): cur = queue.pop(0) if not cur.left and not cur.right: return res if cur.left: queue.append(cur.left) if cur.right: queue.append(cur.right) res += 1 return res
112.Path Sum ---not bug free
Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. For example: Given the below binary tree and sum = 22, 5 / \ 4 8 / / \ 11 13 4 / \ \ 7 2 1 return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.
有个坑,不好描述的坑,仔细思考。
def hasPathSum(self, root, sum): """ :type root: TreeNode :type sum: int :rtype: bool """ return self.help(root, sum) def help(self, root, target): if not root: return False if not root.left and not root.right: if target == root.val: return True else: return False return self.help(root.left, target - root.val) or self.help(root.right, target - root.val)
113.Path Sum II
Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. For example: Given the below binary tree and sum = 22, 5 / \ 4 8 / / \ 11 13 4 / \ / \ 7 2 5 1 return [ [5,4,11,2], [5,8,4,5] ]
backtracking.注意cur.pop()
def pathSum(self, root, sum): """ :type root: TreeNode :type sum: int :rtype: List[List[int]] """ res = [] self.help(root, sum, res, []) return res def help(self, root, target, res, cur): if not root: return if not root.left and not root.right: if target == root.val: cur.append(root.val) res.append(cur[:]) cur.pop() return else: cur.append(root.val) self.help(root.left, target - root.val, res, cur) self.help(root.right, target - root.val, res ,cur) cur.pop()
114.Flatten Binary Tree to Linked List
Given a binary tree, flatten it to a linked list in-place. For example, Given 1 / \ 2 5 / \ \ 3 4 6 The flattened tree should look like: 1 \ 2 \ 3 \ 4 \ 5 \ 6
先序遍历。每次节点任务完成后,更新左右节点。注意左二子为None的更新。右儿子为栈顶。
def flatten(self, root): """ :type root: TreeNode :rtype: void Do not return anything, modify root in-place instead. """ if not root: return root stack = [] stack.append(root) while stack: root = stack.pop() if root.right: stack.append(root.right) if root.left: stack.append(root.left) root.left = None # Attention! if stack: root.right = stack[-1]
115.Distinct Subsequences --- not bug free
Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not). Here is an example: S = "rabbbit", T = "rabbit" Return 3.
dp.dp[i][j]表示s前i个字符的字串和t前j个字符的字串,有多少种方案。
考虑s[i - 1]是否等于t[j - 1],这会影响是否使用s的当前字符s[i - 1].
def numDistinct(self, s, t): """ :type s: str :type t: str :rtype: int """ if s == None or t == None: return 0 if len(s) < len(t): return 0 m = len(s) n = len(t) dp = [[0 for i in xrange(n + 1)] for j in xrange(m + 1)] for i in xrange(m + 1): dp[i][0] = 1 for i in xrange(1, m + 1): for j in xrange(1, n + 1): if s[i - 1] == t[j - 1]: dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j] else: dp[i][j] = dp[i - 1][j] return dp[m][n]
116.Populating Next Right Pointers in Each Node
Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL. Initially, all next pointers are set to NULL. Note: You may only use constant extra space. You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children). For example, Given the following perfect binary tree, 1 / \ 2 3 / \ / \ 4 5 6 7 After calling your function, the tree should look like: 1 -> NULL / \ 2 -> 3 -> NULL / \ / \ 4->5->6->7 -> NULL
层序遍历。
def connect(self, root): if not root: return queue = [] queue.append(root) while queue: size = len(queue) for i in xrange(size): cur = queue.pop(0) cur.next = queue[0] if i != size - 1 else None if cur.left: queue.append(cur.left) if cur.right: queue.append(cur.right)
父亲层处理儿子层的下一节点。也是一层一层的遍历。
1 def connect(self, root): 2 if not root: 3 return 4 while root.left: 5 cur = root 6 while cur: 7 cur.left.next = cur.right 8 if cur.next: 9 cur.right.next = cur.next.left 10 cur = cur.next 11 root = root.left
117.Populating Next Right Pointers in Each Node II
Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tree could be any binary tree? Would your previous solution still work? Note: You may only use constant extra space. For example, Given the following binary tree, 1 / \ 2 3 / \ \ 4 5 7 After calling your function, the tree should look like: 1 -> NULL / \ 2 -> 3 -> NULL / \ \ 4-> 5 -> 7 -> NULL
并不是完全二叉树,则上述方法二不适用,层序遍历仍然有效。
def connect(self, root): if not root: return queue = [] queue.append(root) while queue: size = len(queue) for i in xrange(size): cur = queue.pop(0) cur.next = queue[0] if i != size - 1 else None if cur.left: queue.append(cur.left) if cur.right: queue.append(cur.right)
118.Pascal's Triangle
Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5, Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ]
从第二行开始,出去左右两边的,都等于上一行的相加。
def generate(self, numRows): """ :type numRows: int :rtype: List[List[int]] """ res = [] if numRows < 1: return res res.append([1]) for i in xrange(1, numRows): cur = [1] for j in xrange(i - 1): cur.append(res[i - 1][j] + res[i - 1][j + 1]) cur.append(1) res.append(cur[:]) return res
119.Pascal's Triangle II
Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return [1,3,3,1].
res 和 cur,由res求cur,求得cur之后更新res
def getRow(self, rowIndex): """ :type rowIndex: int :rtype: List[int] """ if rowIndex < 0: return [] res = [1] for i in xrange(1, rowIndex + 1): cur = [1] for j in xrange(1, i): cur.append(res[j - 1] + res[j]) cur.append(1) res = cur return res
120.Triangle
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. For example, given the following triangle [ [2], [3,4], [6,5,7], [4,1,8,3] ] The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).
自底向上的DP.
def minimumTotal(self, triangle): """ :type triangle: List[List[int]] :rtype: int """ if not triangle: return 0 m = len(triangle) dp = [[0 for i in xrange(m)] for j in xrange(m)] for j in xrange(m): dp[m - 1][j] = triangle[m - 1][j] for i in xrange(m - 2, -1, -1): for j in xrange(i + 1): dp[i][j] = min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle[i][j] return dp[0][0]
121.Best Time to Buy and Sell Stock
Say you have an array for which the ith element is the price of a given stock on day i. If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
记录最小值,比最小值小则更新最小值,否则计算收益更新res
def maxProfit(self, prices): """ :type prices: List[int] :rtype: int """ if not prices: return 0 res = 0 min = prices[0] n = len(prices) for i in xrange(1, n): if prices[i] < min: min = prices[i] else: res = max(res, prices[i] - min) return res
122.Best Time to Buy and Sell Stock II
Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
后一天价格比前一天高就加上差价。
def maxProfit(self, prices): """ :type prices: List[int] :rtype: int """ if not prices: return 0 res = 0 n = len(prices) for i in xrange(1, n): if prices[i] > prices[i - 1]: res += prices[i] - prices[i - 1] return res
123.Best Time to Buy and Sell Stock III
Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most two transactions.
dp.left[i]表示前i个一次交易的最大,right[i]表示后i个一次交易的最大。left[i] + right[i]更新res.
def maxProfit(self, prices): """ :type prices: List[int] :rtype: int """ if not prices: return 0 n = len(prices) left = [0] * n right = [0] * n minNum = prices[0] for i in xrange(1, n): if prices[i] < minNum: left[i] = left[i - 1] minNum = prices[i] else: left[i] = max(left[i - 1], prices[i] - minNum) maxNum = prices[n - 1] res = left[n - 1] for i in xrange(n - 2, -1, -1): if prices[i] > maxNum: right[i] = right[i + 1] maxNum = prices[i] else: right[i] = max(right[i + 1], maxNum - prices[i]) res = max(res, left[i] + right[i]) return res
124.Binary Tree Maximum Path Sum
Given a binary tree, find the maximum path sum. For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root. For example: Given the below binary tree, 1 / \ 2 3 Return 6.
递归。注意为None的时候的返回值。
class Solution(object): def maxPathSum(self, root): """ :type root: TreeNode :rtype: int """ return self.help(root).any2any def help(self, root): if not root: return ResultType(-1 << 32, -1 << 32) left = self.help(root.left) right = self.help(root.right) root2any = max(max(0, left.root2any), max(0, right.root2any)) + root.val any2any = max(0, left.root2any) + max(0, right.root2any) + root.val any2any = max(any2any, left.any2any, right.any2any) return ResultType(root2any, any2any) class ResultType(object): def __init__(self, root2any, any2any): self.root2any = root2any self.any2any = any2any
125.Valid Palindrome
Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. For example, "A man, a plan, a canal: Panama" is a palindrome. "race a car" is not a palindrome.
两个指针。
def isPalindrome(self, s): """ :type s: str :rtype: bool """ if not s: return True left = 0 right = len(s) - 1 while left < right: while left < right and not s[left].isalnum(): left += 1 while left < right and not s[right].isalnum(): right -= 1 if s[left].lower() != s[right].lower() : return False left += 1 right -= 1 return True
126.Word Ladder II --- not bug free
Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that: Only one letter can be changed at a time Each transformed word must exist in the word list. Note that beginWord is not a transformed word. For example, Given: beginWord = "hit" endWord = "cog" wordList = ["hot","dot","dog","lot","log","cog"] Return [ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ] Note: Return an empty list if there is no such transformation sequence. All words have the same length. All words contain only lowercase alphabetic characters. You may assume no duplicates in the word list. You may assume beginWord and endWord are non-empty and are not the same.
这个题花了好长时间才ac。主要原因:1.题目要求和之前的不同了,wordList中必须包含endWord;2.python中字典如果不包含key,去获取key的value的时候是会报错的,而java中不会报错,会得到null。所以java中去获取之后看为不为null返回,python中需要去看包不包含这个key。
解题思路:
1.首先是需要获取adjMap.具体做法是去除每一个位置的那个字母得到rep,把相同rep的放到一个list中,然后list中两两互为adj
2.然后需要获取previousMap,由于需要找所有最短路径,所以需要使用记录具体的distanceMap。使用一个queue实现
3.然后回溯即可。
def findLadders(self, beginWord, endWord, wordList): """ :type beginWord: str :type endWord: str :type wordList: List[str] :rtype: List[List[str]] """ if not beginWord or not endWord or not wordList: return [] adjMap = {} wordList = set(wordList) if endWord not in wordList: return [] wordList.add(beginWord) self.getAdjMap(wordList, adjMap, len(beginWord)) # print adjMap previousMap = self.getPreviousMap(adjMap, beginWord, endWord) # print previousMap res = [] cur = [endWord] self.dfs(previousMap, beginWord, endWord, res, cur) return res def dfs(self, previousMap, beginWord, endWord, res, cur): if beginWord == endWord: res.append(cur[:]) return if endWord not in previousMap: return prevList = previousMap[endWord] for prev in prevList: cur.insert(0, prev) self.dfs(previousMap, beginWord, prev, res, cur) cur.pop(0) def getPreviousMap(self, adjMap, beginWord, endWord): previousMap = {} distanceMap = {} previousMap[beginWord] = None distanceMap[beginWord] = 0 queue = [] queue.append(beginWord) while queue: word = queue.pop(0) if word not in adjMap: continue adjList = adjMap[word] for adj in adjList: if adj not in previousMap: previousMap[adj] = [word] distanceMap[adj] = distanceMap[word] + 1 queue.append(adj) elif distanceMap[word] + 1 == distanceMap[adj]: previousMap[adj].append(word) return previousMap def getAdjMap(self, wordList, adjMap, n): for i in xrange(n): repToWord = {} for word in wordList: rep = word[0:i] + word[(i + 1) : n] self.update(rep, word, repToWord) for rep in repToWord: if len(repToWord[rep]) < 2: continue list = repToWord[rep] for str1 in list: for str2 in list: if str1 != str2: self.update(str1, str2, adjMap) def update(self, rep, word, repToWord): if not rep in repToWord: repToWord[rep] = [] repToWord[rep].append(word)
127.Word Ladder
Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that: Only one letter can be changed at a time. Each transformed word must exist in the word list. Note that beginWord is not a transformed word. For example, Given: beginWord = "hit" endWord = "cog" wordList = ["hot","dot","dog","lot","log","cog"] As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", return its length 5. Note: Return 0 if there is no such transformation sequence. All words have the same length. All words contain only lowercase alphabetic characters. You may assume no duplicates in the word list. You may assume beginWord and endWord are non-empty and are not the same.
和上题主要思路一样,只求最短路径,所以只需要找到一条路径即可,不在需要distanceMap,previousMap的value也不再是一个list。
def ladderLength(self, beginWord, endWord, wordList): """ :type beginWord: str :type endWord: str :type wordList: List[str] :rtype: int """ if not beginWord or not endWord or not wordList: return 0 mset = set(wordList) if endWord not in mset: return 0 mset.add(beginWord) adjMap = {} self.getAdjMap(mset, adjMap, len(beginWord)) previousMap = self.getPreviousMap(beginWord, endWord, adjMap) return self.getLength(beginWord, endWord, previousMap) def getPreviousMap(self, beginWord, endWord, adjMap): previousMap = {} previousMap[beginWord] = None queue = [beginWord] while queue: word = queue.pop(0) if word not in adjMap: continue list = adjMap[word] for str in list: if str in previousMap: continue previousMap[str] = word queue.append(str) if str == endWord: return previousMap return previousMap def getLength(self, beginWord, endWord, previousMap): length = 0 while endWord: length += 1 if endWord not in previousMap: return 0 endWord = previousMap[endWord] return length def getAdjMap(self, wordList, adjMap, n): for i in xrange(n): repToWord = {} for word in wordList: rep = word[0 : i] + word[(i + 1) : n] self.update(rep, word, repToWord) for rep in repToWord.keys(): list = repToWord.get(rep) if len(list) < 2: continue for str1 in list: for str2 in list: if str1 != str2: self.update(str1, str2, adjMap) def update(self, str1, str2, map): if str1 not in map: map[str1] = [] map[str1].append(str2)
128.Longest Consecutive Sequence --- not bug free
Total Accepted: 100920 Total Submissions: 278863 Difficulty: Hard Contributor: LeetCode Given an unsorted array of integers, find the length of the longest consecutive elements sequence. For example, Given [100, 4, 200, 1, 3, 2], The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4. Your algorithm should run in O(n) complexity.
首先当然有一种很直观的想法就是排序之后遍历一边,但是这是O(nlogn)的复杂度,需要O(n)的复杂度的话,使用一个set,首先加入所有的元素,然后遍历原来的数组,对于每个数往两边扩展(如果在set中的话,注意扩展之后需要删除这个元素,以免后边又扩进去了。)
def longestConsecutive(self, nums): """ :type nums: List[int] :rtype: int """ if not nums: return 0 mset = set(nums) res = 0 for num in nums: down = num - 1 while down in mset: mset.remove(down) down -= 1 up = num + 1 while up in mset: mset.remove(up) up += 1 res = max(res, up - down - 1) return res
129.Sum Root to Leaf Numbers
Total Accepted: 108165 Total Submissions: 300355 Difficulty: Medium Contributor: LeetCode Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. An example is the root-to-leaf path 1->2->3 which represents the number 123. Find the total sum of all root-to-leaf numbers. For example, 1 / \ 2 3 The root-to-leaf path 1->2 represents the number 12. The root-to-leaf path 1->3 represents the number 13. Return the sum = 12 + 13 = 25.
分治。
res = 0 def sumNumbers(self, root): """ :type root: TreeNode :rtype: int """ global res if not root: return 0 self.help(root, root.val) return self.res def help(self, root, cur): global res if not root.left and not root.right: self.res += cur if root.left: self.help(root.left, cur * 10 + root.left.val) if root.right: self.help(root.right, cur * 10 + root.right.val)
130.Surrounded Regions
Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'.
A region is captured by flipping all 'O's into 'X's in that surrounded region.
For example,
X X X X
X O O X
X X O X
X O X X
After running your function, the board should be:
X X X X
X X X X
X X X X
X O X X
DFS。容易stack溢出,加了最后的if 判断
def solve(self, board): """ :type board: List[List[str]] :rtype: void Do not return anything, modify board in-place instead. """ if not board: return m = len(board) n = len(board[0]) for i in range(m): self.dfs(board, i, 0) self.dfs(board, i , n - 1) for j in range(n): self.dfs(board, 0, j) self.dfs(board, m - 1, j) for i in range(m): for j in range(n): if board[i][j] == '1': board[i][j] = 'O' else: board[i][j] = 'X' def dfs(self, board, i, j): m = len(board) n = len(board[0]) if i < 0 or i >= m or j < 0 or j >= n: return if board[i][j] != 'O': return board[i][j] = '1' self.dfs(board, i + 1, j) self.dfs(board, i - 1, j) self.dfs(board, i, j + 1) if j > 1: self.dfs(board, i, j - 1)
UnionFind。
class Solution(object): def solve(self, board): """ :type board: List[List[str]] :rtype: void Do not return anything, modify board in-place instead. """ if not board: return m = len(board) n = len(board[0]) uf = UnionFind(m * n + 1) dummyNode = m * n for j in range(n): if board[0][j] == 'O': uf.union(self.node(0, j, n), dummyNode) if board[m - 1][j] == 'O': uf.union(self.node(m - 1, j, n), dummyNode) for i in range(m): if board[i][0] == 'O': uf.union(self.node(i, 0, n), dummyNode) if board[i][n - 1] == 'O': uf.union(self.node(i, n - 1, n), dummyNode) for i in range(1, m - 1): for j in range(1, n - 1): if board[i][j] != 'O': continue if board[i - 1][j] == 'O': uf.union(self.node(i - 1, j, n), self.node(i, j, n)) if board[i + 1][j] == 'O': uf.union(self.node(i + 1, j, n), self.node(i, j, n)) if board[i][j - 1] == 'O': uf.union(self.node(i, j - 1, n), self.node(i, j, n)) if board[i][j + 1] == 'O': uf.union(self.node(i, j + 1, n), self.node(i, j, n)) for i in range(m): for j in range(n): if uf.find(self.node(i, j, n)) == uf.find(dummyNode): board[i][j] = 'O' else: board[i][j] = 'X' def node(self, i, j, n): return i * n + j; class UnionFind(object): def __init__(self, n): self.count = n self.ids = [i for i in range(n)] self.sz = [1 for i in range(n)] def union(self, p, q): i = self.find(p) j = self.find(q) if i == j: return elif self.sz[i] < self.sz[j]: self.ids[i] = j self.sz[j] += self.sz[i] self.count -= 1 else: self.ids[j] = i self.sz[i] += self.sz[j] self.count -= 1 def find(self, p): while self.ids[p] != p: self.ids[p] = self.ids[self.ids[p]] p = self.ids[p] return p def count(self): return self.count