目录
1. Two Sum
2. Add Two Numbers
3. Longest Substring Without Repeating Characters
4. Median of Two Sorted Arrays
5. Longest Palindromic Substring
11. Container With Most Water
15. 3Sum
17. Letter Combinations of a Phone Number
18. 4Sum
19. Remove Nth Node From End of List
20. Valid Parentheses
21. Merge Two Sorted Lists
22. Generate Parentheses
24. Swap Nodes in Pairs
25. K个一组翻转链表
31. Next Permutation
33. Search in Rotated Sorted Array
34. Find First and Last Position of Element in Sorted Array
39. Combination Sum
46. Permutations
48. Rotate Image
49. Group Anagrams
53. Maximum Subarray
55. Jump Game
56. Merge Intervals
62. Unique Paths
63. 不同路径2
64. Minimum Path Sum
75. Sort Colors
78. Subsets
79. Word Search
81. Search in Rotated Sorted Array II
94. Binary Tree Inorder Traversal
95. 不同的二叉搜索树 II
96. Unique Binary Search Trees
98. Validate Binary Search Tree
101. Symmetric Tree
102. Binary Tree Level Order Traversal
104. Maximum Depth of Binary Tree
105. Construct Binary Tree from Preorder and Inorder Traversal
114. Flatten Binary Tree to Linked List
121. Best Time to Buy and Sell Stock
128. 最长连续序列
129. 求根到叶子节点数字之和
136. Single Number
138. 复制带随机指针的链表
139. Word Break
141. Linked List Cycle
142. Linked List Cycle II
148. Sort List
152. Maximum Product Subarray
169. Majority Element
198. House Robber
200. 岛屿数量
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.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].
class Solution { public int[] twoSum(int[] nums, int target) { //一个HashMap解决 HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); for(int i = 0; i < nums.length; i++) { if(map.containsKey(target - nums[i])) return new int[]{map.get(target - nums[i]), i}; map.put(nums[i], i); } return null; } }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.
Example:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 Explanation: 342 + 465 = 807.
class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode head = l1; //head doesn't change ListNode tail = head; //tail is the last completed Node, always not null int a = 0; //进位标记 while(l1 != null && l2 != null){ l1.val += (l2.val + a); if(l1.val >= 10){ a = 1; l1.val -= 10; } else a = 0; tail = l1; l1 = l1.next; l2 = l2.next; } if(l2 != null) tail.next = l2; while(tail.next != null){ //a为0退出,否则继续加下去 tail.next.val += a; if(tail.next.val >= 10){ a = 1; tail.next.val -= 10; } else{ a = 0; break; } tail = tail.next; } if(a == 1){ //新进一位 ListNode last = new ListNode(1); tail.next = last; } return head; } }Given a string, find the length of the longest substring without repeating characters.
Example 1:
Input: "abcabcbb" Output: 3 Explanation: The answer is "abc", with the length of 3. Example 2:
Input: "bbbbb" Output: 1 Explanation: The answer is "b", with the length of 1. Example 3:
Input: "pwwkew" Output: 3 Explanation: 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.
class Solution { public int lengthOfLongestSubstring(String s) { HashMap map = new HashMap(); int max = 0, start = 0; for(int i = 0; i < s.length(); i++){ if(s.length() - start <= max) break; //发现重复时,只有重复字符的下一位>start时才需要更新start if(map.containsKey(s.charAt(i))) start = Math.max(start, (int)map.get(s.charAt(i)) + 1); max = Math.max(max, i - start + 1); map.put(s.charAt(i),i); } return max; } }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)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1, 3] nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2] nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
class Solution { public double findMedianSortedArrays(int[] nums1, int[] nums2) { int m = nums1.length; int n = nums2.length; if((m + n) % 2 == 1) //合并后总长度为奇数 return findKthSmall(nums1, 0, nums2, 0, (m + n) / 2 + 1) * 1.0; else //合并后总长度为偶数 return (findKthSmall(nums1, 0, nums2, 0, (m + n) / 2) + findKthSmall(nums1, 0, nums2, 0, (m + n) / 2 + 1)) / 2.0; } //寻找两个数组合并后的第k小元素 public int findKthSmall(int[] nums1, int start1, int[] nums2, int start2, int k) { if(start1 >= nums1.length) return nums2[start2 + k - 1]; if(start2 >= nums2.length) return nums1[start1 + k - 1]; if(k == 1) //递归出口,直接返回首元素中更小的 return Math.min(nums1[start1], nums2[start2]); //每次扣除k/2个比目标值小的元素,通过比较两个数组的前k/2个元素,决定从哪个数组中扣除 //本数组长度不够数k/2个时,无论本数组的值如何,另一个数组的前k/2个都必定小于目标值可扣除 //因此本数组的mid赋值为MAX_VALUE,以便于全部留下 //mid是指数组第k/2个元素,而不是数组长度的mid int mid1 = start1 + k / 2 - 1 >= nums1.length ? Integer.MAX_VALUE : nums1[start1 + k / 2 - 1]; int mid2 = start2 + k / 2 - 1 >= nums2.length ? Integer.MAX_VALUE : nums2[start2 + k / 2 - 1]; if(mid1 < mid2) //更小的mid说明start到mid都小于目标值,可扣除 return findKthSmall(nums1, start1 + k / 2, nums2, start2, k - k / 2); else return findKthSmall(nums1, start1, nums2, start2 + k / 2, k - k / 2); } }Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: "babad" Output: "bab" Note: "aba" is also a valid answer. Example 2:
Input: "cbbd" Output: "bb"
class Solution { public String longestPalindrome(String s) { int[] start = new int[]{0}; int[] max = new int[]{0}; //每个位置都作为子串中心点调用一次函数,分奇数和偶数个字符两种情况 for(int i = 0; i < s.length(); i++) { extendPalindromic(s, i, i, max, start); extendPalindromic(s, i, i + 1, max, start); } return s.substring(start[0], start[0] + max[0]); } //以j和k作为中心点向两侧延伸,更新最大长度max[0]和起始位置start[0] public void extendPalindromic(String s, int j, int k, int[] max, int[] start) { while(j >= 0 && k < s.length() && s.charAt(j) == s.charAt(k)) { j--; k++; } if(k - j - 1 > max[0]) { start[0] = j + 1; max[0] = k - j - 1; } } }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.
The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.
class Solution { public int maxArea(int[] height) { int max = 0; int start = 0, end = height.length - 1; while(start < end) { //计算容积,并更新max max = Math.max(max, (end - start) * Math.min(height[start], height[end])); if(height[start] < height[end]) //每次都抛弃更矮的边 start++; else end--; } return max; } }Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
class Solution { public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> result = new ArrayList(); Arrays.sort(nums); //排序升序 for(int i = 0; i < nums.length - 2; i++) { //跳过已经遍历过的nums[i - 1],保证第一个值不重复 if(i > 0 && nums[i] == nums[i - 1]) continue; int j = i + 1, k = nums.length - 1; while(j < k) { int sum = nums[i] + nums[j] + nums[k]; if(sum == 0) { result.add(Arrays.asList(nums[i], nums[j], nums[k])); j++; k--; //(只需在sum等于0时)保证第二、三个值不重复 while(j < k && nums[j] == nums[j - 1]) j++; while(j < k && nums[k] == nums[k + 1]) k--; } else if(sum > 0) k--; else j++; } } return result; } }Given a string containing digits from 2-9 inclusive, 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. Note that 1 does not map to any letters.
Example:
Input: "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
Note:
Although the above answer is in lexicographical order, your answer could be in any order you want.
class Solution { public List<String> letterCombinations(String digits) { List<String> result = new ArrayList<String>(); if(digits.length() == 0) return result; char[][] letters = new char[][]{ {'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'}, }; result.add(""); for(int i = 0; i < digits.length(); i++) { int number = digits.charAt(i) - '0'; if(number < 2 || number > 9) continue; result = addOneLetter(result, letters[number - 2]); } return result; } //添加一个字母,参数为需要改动的strArr和1个数字代表的字母列表 public List<String> addOneLetter(List<String> strArr, char[] charArr) { //按添加一个字母后的长度初始化String[] String[] result = new String[strArr.size() * charArr.length]; int i = 0, j = 0, k = 0; //分别为result下标,原strArr下标,字母列表下标 while(i < result.length) { result[i] = new String(strArr.get(j)) + charArr[k]; i++; if(i % charArr.length == 0) j++; k = (k + 1) % charArr.length; } return Arrays.asList(result); } }Given an array nums of n integers and an integer target, are there elements a, b, c, and din nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
The solution set must not contain duplicate quadruplets. A solution set is: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
Example:
Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.
class Solution { public List<List<Integer>> fourSum(int[] nums, int target) { List<List<Integer>> result = new ArrayList<List<Integer>>(); if(nums.length < 4) return result; //对后3个数和3sum相同,只不过判断sum == 0 改为 == target - nums[i] Arrays.sort(nums); int n = nums.length; for(int i = 0; i < n - 3; i++) { //前面的和太大,跳出循环 if(nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break; //后面的和还不够,继续下一次 if(nums[i] + nums[n - 1] + nums[n - 2] + nums[n - 3] < target) continue; if(i > 0 && nums[i] == nums[i - 1]) continue; for(int j = i + 1; j < n - 2; j++) { if(nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break; if(nums[i] + nums[j] + nums[n - 1] + nums[n - 2] < target) continue; if(j > i + 1 && nums[j] == nums[j - 1]) continue; int k = j + 1, l = n - 1; while(k < l) { //对后两个数开始用while循环 int sum = nums[j] + nums[k] + nums[l]; if(sum == target - nums[i]) { result.add(Arrays.asList(nums[i], nums[j], nums[k], nums[l])); while(k < l && nums[k] == nums[k + 1]) k++; while(k < l && nums[l] == nums[l - 1]) l--; k++; l--; } else if(sum > target - nums[i]) l--; else k++; } } } return result; } }Medium
1959146FavoriteShare
Given a linked list, remove the n-th node from the end of list and return its head.
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.
Note:
Given n will always be valid.
Follow up:
Could you do this in one pass?
class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode l1 = head, l2 = head; int i; for(i = 0; i < n && l1.next != null; i++) //l1先移动n步 l1 = l1.next; while(l1.next != null){ //l1移动到最后一个节点,此时l2.next为需要删除的节点 l1 = l1.next; l2 = l2.next; } if(i == n){ //说明l1成功地先移动了n步,n合理,可以删除l2.next l1 = l2.next.next; l2.next = l1; } else head = head.next; //否则删掉头节点 return head; } }Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
1.Open brackets must be closed by the same type of brackets. 2.Open brackets must be closed in the correct order.
Note that an empty string is also considered valid.
Example 1:
Input: "()"
Output: true
Example 2:
Input: "()[]{}"
Output: true
Example 3:
Input: "(]"
Output: false
Example 4:
Input: "([)]"
Output: false
Example 5:
Input: "{[]}"
Output: true
class Solution { public boolean isValid(String s) { //一个栈解决 Stack stack = new Stack(); for(int i = 0; i < s.length(); i++) { char c = s.charAt(i); switch(c) { case ')': if(stack.empty() || (char)stack.pop() != '(') return false; break; case ']': if(stack.empty() || (char)stack.pop() != '[') return false; break; case '}': if(stack.empty() || (char)stack.pop() != '{') return false; break; default: stack.push(c); } } if(stack.empty()) return true; else return false; } }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.
Example:
Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4
class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { //偷懒用递归解决 if(l1 == null) return l2; if(l2 == null) return l1; if(l1.val <= l2.val) { l1.next = mergeTwoLists(l1.next, l2); return l1; } else { l2.next = mergeTwoLists(l1, l2.next); return l2; } } }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:
[ "((()))", "(()())", "(())()", "()(())", "()()()" ]
class Solution { public List<String> generateParenthesis(int n) { List<String> result = new ArrayList<String>(); backtrack(result, "", 0, 0, n); return result; } //回溯算法 public void backtrack(List<String> result, String s, int numOpen, int numClose, int n) { if(s.length() == 2 * n){ result.add(s); return; } //先判断能否加'(' if(numOpen < n) backtrack(result, s + "(", numOpen + 1, numClose, n); //再判断能否加')' if(numClose < numOpen) backtrack(result, s + ")", numOpen, numClose + 1, n); } }Given a linked list, swap every two adjacent nodes and return its head.
You may not modify the values in the list's nodes, only nodes itself may be changed.
Example: Given 1->2->3->4, you should return the list as 2->1->4->3.
class Solution { public ListNode swapPairs(ListNode head) { //先判断长度是否>=2 int n = 0; for(ListNode r = head; r != null && n < 2; r = r.next) n++; if(n < 2) return head; else{ //递归即可 ListNode r = head.next.next; ListNode start = head.next; head.next.next = head; head.next = swapPairs(r); return start; } } }给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明 : 你的算法只能使用常数的额外空间。 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
class Solution { public ListNode reverse(ListNode head) { ListNode tail = null; while(head != null) { ListNode temp = head.next; head.next = tail; tail = head; head = temp; } return tail; } public ListNode reverseKGroup(ListNode head, int k) { //先翻转前k个,再递归 ListNode p = head; ListNode pre = null; int i = 0; for(; i < k && p != null; i++) { pre = p; p = p.next; } //长度不够k if(i < k) { return head; } //断开并翻转 pre.next = null; ListNode res = reverse(head); //翻转后head即尾节点,连接递归的后续部分 head.next = reverseKGroup(p, k); return res; } }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 and use only constant 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
class Solution { public void nextPermutation(int[] nums) { if(nums == null || nums.length <= 1) return; //思路是把临界元素置换成下一个更大的元素,再把逆序的后半段变成升序 int i = nums.length - 2; while(i >= 0 && nums[i] >= nums[i + 1]) //跳过结尾逆序,找到第一个顺序对的前者nums[i] i--; if(i >= 0) { int j = nums.length - 1; while(nums[j] <= nums[i]) //从后向前找到第一个比nums[i]大的 j--; int temp = nums[i]; //和nums[i]交换 nums[i] = nums[j]; nums[j] = temp; } //i + 1到结尾全部反转(变成升序) for(int j = i + 1, k = nums.length - 1; j <= k; j++, k--) { int temp = nums[j]; nums[j] = nums[k]; nums[k] = temp; } } }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.
Your algorithm's runtime complexity must be in the order of O(log n).
Example 1: Input: nums = [4,5,6,7,0,1,2], target = 0 Output: 4
Example 2: Input: nums = [4,5,6,7,0,1,2], target = 3 Output: -1
class Solution { public int search(int[] nums, int target) { int start = 0, end = nums.length - 1; while(start <= end) { int mid = (start + end) / 2; if(nums[mid] == target) return mid; if(nums[start] < nums[end]) { //整个都是升序时正常二分查找 if(target < nums[mid]) end = mid - 1; else start = mid + 1; } //半边是只包括mid的部分 else if(nums[mid] >= nums[start]) { //左半边是升序,mid可能等于start所以要加上= if(target > nums[mid]) { //比nums[mid]大的一定在右边 start = mid + 1; } else { //比nums[mid]小,分两种情况 if(target >= nums[start]) //target在左半边 end = mid - 1; else //target在右半边 start = mid + 1; } } else { //右半边是升序 if(target < nums[mid]) { //比nums[mid]小的一定在左边 end = mid - 1; } else { //比nums[mid]大,分两种情况 if(target <= nums[end]) //target在右半边 start = mid + 1; else //target在左半边 end = mid - 1; } } } return -1; } }Given an array of integers nums 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].
Example 1:
Input: nums = [5,7,7,8,8,10], target = 8 Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10], target = 6 Output: [-1,-1]
class Solution { public int[] searchRange(int[] nums, int target) { int[] result = new int[]{-1, -1}; //先二分查找 int start = 0, end = nums.length - 1; int mid = (start + end) / 2; while(start <= end) { if(nums[mid] == target) { result[0] = mid; result[1] = mid; break; } else if(nums[mid] < target) { start = mid + 1; } else { end = mid - 1; } mid = (start + end) / 2; } //如果找到,则向两侧遍历找到两端下标 if(result[0] != -1) { int i = result[0], j = result[1]; while(i >= start && nums[i] == target) i--; //注意先判断i>=start result[0] = i + 1; while(j <= end && nums[j] == target) j++; result[1] = j - 1; } return result; } }Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.
The same repeated number may be chosen from candidates unlimited number of times.
Note:
All numbers (including target) will be positive integers. The solution set must not contain duplicate combinations.
Example 1: Input: candidates = [2,3,6,7], target = 7, A solution set is: [ [7], [2,2,3] ]
Example 2: Input: candidates = [2,3,5], target = 8, A solution set is: [ [2,2,2,2], [2,3,3], [3,5] ]
class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> list = new ArrayList<>(); Arrays.sort(candidates); backtrack(list, new ArrayList<>(), candidates, target, 0); return list; } //回溯算法搞定 private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] candidates, int remain, int start) { if(remain < 0) return; else if(remain == 0) list.add(new ArrayList<>(tempList)); //注意是new ArrayList复制一个新的才对 else { for(int i = start; i < candidates.length; i++) { tempList.add(candidates[i]); //因为元素可以重复使用,所以最后一个参数start还是i backtrack(list, tempList, candidates, remain - candidates[i], i); tempList.remove(tempList.size() - 1); //可以看到tempList的add和remove是成对的,循环进行一次tempList长度不变 //即使中间有递归调用也不会影响 } } } }Given a collection of distinct integers, return all possible permutations.
Example:
Input: [1,2,3] Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
class Solution { public List<List<Integer>> permute(int[] nums) { List<List<Integer>> result = new ArrayList<List<Integer>>(); result.add(new ArrayList<Integer>()); for(int i = 0; i < nums.length; i++) { addOneNum(nums, i, result); //插入第i个数,第二个参数传下标i(要用到) } return result; } //不过这个循环结果不是例子那样 private void addOneNum(int[] nums, int i, List<List<Integer>> result) { int size1 = result.size(); int size2 = i; //原来的每个序列都会变为 size2+1 个新序列 for(int j = 0; j < size1; j++) { //j * (size2 + 1) is the right index to add //取出旧序列,并从result移除 List<Integer> tempList = result.get(j * (size2 + 1)); result.remove(j * (size2 + 1)); //新元素nums[i]可以插入的位置有 size2+1 个 for(int k = 0; k < size2 + 1; k++) { List<Integer> newList = new ArrayList<Integer>(tempList); newList.add(k, nums[i]); result.add(j * (size2 + 1), newList); } } } }You are given an n x n 2D matrix representing an image.
Rotate the image by 90 degrees (clockwise).
Note:
You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.
Example 1: Given input matrix = [ [1,2,3], [4,5,6], [7,8,9] ], rotate the input matrix in-place such that it becomes: [ [7,4,1], [8,5,2], [9,6,3] ]
Example 2: Given input matrix = [ [ 5, 1, 9,11], [ 2, 4, 8,10], [13, 3, 6, 7], [15,14,12,16] ], rotate the input matrix in-place such that it becomes: [ [15,13, 2, 5], [14, 3, 4, 1], [12, 6, 8, 9], [16, 7,10,11] ]
class Solution { public void rotate(int[][] matrix) { for(int i = 0; i < matrix.length / 2; i++) { //圈数 for(int j = i; j < matrix[i].length - i - 1; j++) { int temp = matrix[i][j]; //每次4个数旋转90度 matrix[i][j] = matrix[matrix.length - 1 - j][i]; matrix[matrix.length - 1 - j][i] = matrix[matrix.length - 1 - i][matrix.length - 1 - j]; matrix[matrix.length - 1 - i][matrix.length - 1 - j] = matrix[j][matrix.length - 1 - i]; matrix[j][matrix.length - 1 - i] = temp; } } } }Given an array of strings, group anagrams together.
Example: Input: ["eat", "tea", "tan", "ate", "nat", "bat"], Output: [ ["ate","eat","tea"], ["nat","tan"], ["bat"] ]
Note: All inputs will be in lowercase. The order of your output does not matter.
class Solution { public List<List<String>> groupAnagrams(String[] strs) { if (strs == null || strs.length == 0) return new ArrayList<List<String>>(); //用一个HashMap解决,最后用map.values()获得value集合 Map<String, List<String>> map = new HashMap<String, List<String>>(); for (String s : strs) { char[] ca = s.toCharArray(); Arrays.sort(ca); String keyStr = String.valueOf(ca); if (!map.containsKey(keyStr)) map.put(keyStr, new ArrayList<String>()); map.get(keyStr).add(s); } return new ArrayList<List<String>>(map.values()); } }Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Example: Input: [-2,1,-3,4,-1,2,1,-5,4], Output: 6 Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up: If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
class Solution { public int maxSubArray(int[] nums) { if(nums.length == 0) return 0; int maxSum = Integer.MIN_VALUE; int sum = 0; for(int i = 0; i < nums.length; i++){ //每个sum都要求包含当前nums[i] if(sum < 0) sum = nums[i]; //旧的sum为负数,则抛弃 else sum += nums[i]; maxSum = Math.max(sum, maxSum); } return maxSum; } }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.
Example 1: Input: [2,3,1,1,4] Output: true Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
Example 2: Input: [3,2,1,0,4] Output: false Explanation: You will always arrive at index 3 no matter what. Its maximum jump length is 0, which makes it impossible to reach the last index.
class Solution { public boolean canJump(int[] nums) { int max = 0; //max为当前可到达的最远处 for(int i = 0; i < nums.length; i++){ if(max < i) return false; //当前i无法到达,返回false max = Math.max(max, i + nums[i]); } return true; } }Given a collection of intervals, merge all overlapping intervals.
Example 1: Input: [[1,3],[2,6],[8,10],[15,18]] Output: [[1,6],[8,10],[15,18]] Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
Example 2: Input: [[1,4],[4,5]] Output: [[1,5]] Explanation: Intervals [1,4] and [4,5] are considered overlapping.
class Solution { public int[][] merge(int[][] intervals) { //区间合并的关键点在于start和end分别排序,再合并结果相同 int n = intervals.length; int[] starts = new int[n]; int[] ends = new int[n]; for (int i = 0; i < n; i++) { //保存starts和ends数组 starts[i] = intervals[i][0]; ends[i] = intervals[i][1]; } //分别排序 Arrays.sort(starts); Arrays.sort(ends); int[][] res = new int[intervals.length][2]; int k = 0; //res的下标 for (int i = 0, j = 0; i < n; i++) { // j is start of interval. if (i == n - 1 || starts[i + 1] > ends[i]) { //分割点 res[k++] = new int[]{starts[j], ends[i]}; j = i + 1; } } return Arrays.copyOf(res, k); } }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?
Above is a 7 x 3 grid. How many possible unique paths are there?
Note: m and n will be at most 100.
Example 1: Input: m = 3, n = 2 Output: 3 Explanation: From the top-left corner, there are a total of 3 ways to reach the bottom-right corner: 1. Right -> Right -> Down 2. Right -> Down -> Right 3. Down -> Right -> Right
Example 2: Input: m = 7, n = 3 Output: 28
class Solution { public int uniquePaths(int m, int n) { //m - 1 个 right, n - 1 个 down //m + n - 2 个数中取 n - 1个 down int max = Math.max(m, n); int min = Math.min(m, n); if(min == 1) return 1; //组合数计算公式(取min - 1个,计算更快) long result = 1; for(int i = max + min - 2; i > max - 1; i--) result *= i; return (int)(result / factorial(min - 1)); } public int factorial(int x) { for(int i = x - 1; i > 0; i--) x *= i; return x; } }一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1 和 0 来表示。
说明:m 和 n 的值均不超过 100。
示例 1:
输入: [ [0,0,0], [0,1,0], [0,0,0] ] 输出: 2
解释: 3x3 网格的正中间有一个障碍物。 从左上角到右下角一共有 2 条不同的路径: 1. 向右 -> 向右 -> 向下 -> 向下 2. 向下 -> 向下 -> 向右 -> 向右
class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { //新矩阵每个元素表示起点到此的路径数,上边和左边一律是1,再由相邻元素求出所有元素 //矩阵路径问题一律用此方法 //这道不需要新建矩阵,直接在原矩阵上修改就可 for(int i = 0; i < obstacleGrid.length; i++) { for(int j = 0; j < obstacleGrid[0].length; j++) { //障碍不可到达,需要先判断以便预防终点是障碍的情况 if(obstacleGrid[i][j] == 1) { obstacleGrid[i][j] = 0; } //否则若是起点,路径数为1 else if(i == 0 && j == 0) { obstacleGrid[i][j] = 1; } //上边和左边 else if(i == 0 || j == 0){ obstacleGrid[i][j] = i == 0 ? obstacleGrid[i][j-1] : obstacleGrid[i-1][j]; } else { obstacleGrid[i][j] = obstacleGrid[i - 1][j] + obstacleGrid[i][j - 1]; } } } return obstacleGrid[obstacleGrid.length - 1][obstacleGrid[0].length - 1]; } }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.
Example: Input: [ [1,3,1], [1,5,1], [4,2,1] ] Output: 7 Explanation: Because the path 1→3→1→1→1 minimizes the sum.
class Solution { public int minPathSum(int[][] grid) { //贪心法,从尾到头依次计算每个节点到结尾的minPathSum int[][] minSum = new int[grid.length][grid[0].length]; int i = grid.length - 1; int j = grid[0].length - 1; minSum[i][j] = grid[i][j]; //先计算两个边界的minPathSum while(--i >= 0) minSum[i][j] = grid[i][j] + minSum[i + 1][j]; i = grid.length - 1; while(--j >= 0) minSum[i][j] = grid[i][j] + minSum[i][j + 1]; //双重循环,计算每个节点到结尾的minPathSum for(i = grid.length - 2; i >= 0; i--) { for(j = grid[0].length - 2; j >= 0; j--) { minSum[i][j] = grid[i][j] + Math.min(minSum[i + 1][j], minSum[i][j + 1]); } } return minSum[0][0]; } }Given an array with n objects colored red, white or blue, sort them in-place 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.
Note: You are not suppose to use the library's sort function for this problem.
Example: Input: [2,0,2,1,1,0] Output: [0,0,1,1,2,2]
Follow up: A rather straight forward solution is a two-pass algorithm using counting sort. First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's. Could you come up with a one-pass algorithm using only constant space?
class Solution { public void sortColors(int[] nums) { int p1 = 0, p2 = nums.length - 1; int i = 0; while(i <= p2) { if(nums[i] == 0) { //所有0移到前面, nums[p1]是遍历过的,所以i不需要静止 nums[i] = nums[p1]; nums[p1] = 0; p1++; } if(nums[i] == 2) { //所有2移到后面 nums[i] = nums[p2]; nums[p2] = 2; p2--; i--; //i要静止检查新的nums[i] } i++; } } }Given a set of distinct integers, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.
Example:
Input: nums = [1,2,3] Output: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]
class Solution { public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> result = new ArrayList<List<Integer>>(); result.add(new ArrayList<Integer>()); for(int i = 0; i < nums.length; i++) { //逐个加入新元素 addToSubsets(result, nums[i]); } return result; } public void addToSubsets(List<List<Integer>> result, int number) { int size = result.size(); //先保存size //在原来的基础上每个list都add新元素,就构成要添加的所有list for(int j = 0; j < size; j++) { List<Integer> list = new ArrayList<Integer>(); list.addAll(result.get(j)); list.add(number); result.add(list); } } }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.
Example:
board = [ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E'] ]
Given word = "ABCCED", return true. Given word = "SEE", return true. Given word = "ABCB", return false.
class Solution { public boolean exist(char[][] board, String word) { for(int i = 0; i < board.length; i++) { for(int j = 0; j < board[i].length; j++) { if(exist(board, i, j, word.toCharArray(), 0)) return true; } } return false; } //简单回溯算法 private boolean exist(char[][] board, int i, int j, char[] word, int count) { if(count == word.length) return true; if(i < 0 || j < 0 || i == board.length || j == board[i].length) return false; if(board[i][j] != word[count]) return false; board[i][j] ^= 256; //mask the first correct letter, 再经过时一定不等于word中字母 boolean result = exist(board, i + 1, j, word, count + 1) || exist(board, i - 1, j, word, count + 1) || exist(board, i, j + 1, word, count + 1) || exist(board, i, j - 1, word, count + 1); board[i][j] ^= 256; //解开mask return result; } }Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]).
You are given a target value to search. If found in the array return true, otherwise return false.
Example 1: Input: nums = [2,5,6,0,0,1,2], target = 0 Output: true
Example 2: Input: nums = [2,5,6,0,0,1,2], target = 3 Output: false
class Solution { public boolean search(int[] nums, int target) { return binarySearch(nums, target, 0, nums.length - 1); } //二分查找 public boolean binarySearch(int[] nums, int target, int start, int end) { while(start <= end) { int mid = (start + end) / 2; if(target == nums[mid]) return true; if(nums[mid] > nums[start]) { //说明左半边包括mid是升序 if(target >= nums[start] && target < nums[mid]) //target在左半边 end = mid - 1; else //否则在左半边 start = mid + 1; } else if(nums[mid] < nums[end]){ //说明右半边包括mid是升序 if(target > nums[mid] && target <= nums[end]) //target在右半边 start = mid + 1; else //否则在右半边 end = mid - 1; } else //不清楚顺序,直接两边都判断 return binarySearch(nums, target, start, mid - 1) || binarySearch(nums, target, mid + 1, end); } return false; } }Given a binary tree, return the inorder traversal of its nodes' values.
Example:
Input: [1,null,2,3] 1 \ 2 / 3
Output: [1,3,2]
class Solution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> result = new ArrayList<Integer>(); inorder(root, result); return result; } //简单中序遍历 public void inorder(TreeNode root, List<Integer> result) { if(root == null) return; inorder(root.left, result); result.add(root.val); inorder(root.right, result); } }给定一个整数 n,生成所有由 1 ... n 为节点所组成的二叉搜索树。
输入: 3 输出: [ [1,null,3,2], [3,2,null,1], [3,1,null,null,2], [2,1,3], [1,null,2,null,3] ] 解释: 以上的输出对应以下 5 种不同结构的二叉搜索树:
1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
class Solution { public List<TreeNode> generateTrees(int n) { return generateTrees(1, n); } public List<TreeNode> generateTrees(int start, int end) { //递归得到子树的List,再逐个遍历组装成当前层次的新树 List<TreeNode> res = new ArrayList<TreeNode>(); if(start == end) { //递归出口,单个节点 res.add(new TreeNode(start)); return res; } else if(start > end) return res; //下面是start < end 的情况 List<TreeNode> leftRes; //左子树List List<TreeNode> rightRes; //右子树List rightRes = generateTrees(start + 1, end); //处理左端点 for(TreeNode right : rightRes) { TreeNode root = new TreeNode(start); root.right = right; res.add(root); } for(int i = start + 1; i < end; i++) { //每个元素都可以作为根节点,两个端点时特殊处理 leftRes = generateTrees(start, i - 1); rightRes = generateTrees(i + 1, end); for(TreeNode left : leftRes) { for(TreeNode right : rightRes) { TreeNode root = new TreeNode(i); root.left = left; root.right = right; res.add(root); } } } leftRes = generateTrees(start, end - 1); //处理右端点 for(TreeNode left : leftRes) { TreeNode root = new TreeNode(end); root.left = left; res.add(root); } return res; } }Given n, how many structurally unique BST's (binary search trees) that store values 1 ... n?
Example: Input: 3 Output: 5 Explanation: 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
class Solution { public int numTrees(int n) { if(n <= 2) return n; //用数组不用递归,可以更快 int[] nums = new int[n + 1]; //为了更容易理解nums[0]不放数据 nums[1] = 1; nums[2] = 2; for(int i = 3; i <= n; i++) { function(i, nums); } return nums[n]; } public void function(int n, int[] nums) { nums[n] = 0; nums[n] += nums[n - 1] * 2; //左右子数分别为空时 for(int i = 1; i < n / 2; i++) { //左子树i个节点,右子树n-1-i个 nums[n] += nums[i] * nums[n - 1 - i] * 2; } if(n % 2 == 1) //n为奇数时,加上左右都为n/2个的情况 nums[n] += Math.pow(nums[n / 2], 2); } }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 thanthe 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 Input: [2,1,3] Output: true
Example 2: 5 / \ 1 4 / \ 3 6 Input: [5,1,4,null,null,3,6] Output: false Explanation: The root node's value is 5 but its right child's value is 4.
class Solution { public boolean isValidBST(TreeNode root) { return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE); } public boolean isValidBST(TreeNode root, long min, long max) { if(root == null) return true; //必须要 min < root.val < max if(root.val >= max || root.val <= min) return false; //递归缩小范围 return isValidBST(root.left, min, root.val) && isValidBST(root.right, root.val, max); } }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
class Solution { public boolean isSymmetric(TreeNode root) { if(root == null) return true; else return mirror(root.left, root.right); } //判断两个树互为镜像 public boolean mirror(TreeNode a, TreeNode b) { if(a == null && b == null) return true; if(a != null && b != null){ if(a.val != b.val) return false; else return mirror(a.left, b.right) && mirror(a.right, b.left); } else return false; } }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] ]
class Solution { public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> res = new LinkedList<List<Integer>>(); if(root == null) return res; preOrder(root, 0, res); return res; } //带深度参数的前序遍历即可 public void preOrder(TreeNode root, int depth, List<List<Integer>> res) { if(root != null) { if(depth + 1 > res.size()){ List<Integer> list = new LinkedList<Integer>(); list.add(root.val); res.add(list); } else{ List<Integer> list = res.get(depth); list.add(root.val); } preOrder(root.left, depth + 1, res); preOrder(root.right, depth + 1, res); } } }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.
Note: A leaf is a node with no children.
Example: Given binary tree [3,9,20,null,null,15,7],
3 / \ 9 20 / \ 15 7 return its depth = 3.
class Solution { public int maxDepth(TreeNode root) { if(root == null) return 0; else return Math.max(maxDepth(root.left) + 1, maxDepth(root.right) + 1); } }Given preorder and inorder traversal of a tree, construct the binary tree.
Note: You may assume that duplicates do not exist in the tree.
For example, given
preorder = [3,9,20,15,7] inorder = [9,3,15,20,7] Return the following binary tree:
3 / \ 9 20 / \ 15 7
public class Solution { //剑指offer中做过,copy过来 public TreeNode reConstructBinaryTree(int [] pre,int [] in) { return reConstructBinaryTree(pre, 0, pre.length - 1, in, 0, in.length - 1); } //用下标获取每个子树的前序和中序序列 public TreeNode reConstructBinaryTree(int [] pre, int preStart, int preEnd, int [] in, int inStart, int inEnd) { if(preStart > preEnd || inStart > inEnd) //序列为空,返回null return null; TreeNode res = new TreeNode(pre[preStart]); //前序第1个值是根节点 if(preStart == preEnd) //只有一个节点 return res; int leftCount = 0; //左子树的大小 for(int i = inStart; in[i] != pre[preStart]; i++) leftCount++; res.left = reConstructBinaryTree(pre, preStart + 1, preStart + leftCount, in, inStart, inStart + leftCount - 1); res.right = reConstructBinaryTree(pre, preStart + leftCount + 1, preEnd, in, inStart + leftCount + 1, inEnd); return res; } }Given a binary tree, flatten it to a linked list in-place.
For example, given the following tree:
1 / \ 2 5 / \ \ 3 4 6 The flattened tree should look like:
1 \ 2 \ 3 \ 4 \ 5 \ 6
class Solution { public void flatten(TreeNode root) { if(root == null) return; TreeNode left = root.left; TreeNode right = root.right; root.left = null; flatten(left); root.right = left; while(root.right != null) //遍历至最右 root = root.right; flatten(right); root.right = right; return; } }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 (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.
Note that you cannot sell a stock before you buy one.
Example 1: Input: [7,1,5,3,6,4] Output: 5 Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. Not 7-1 = 6, as selling price needs to be larger than buying price.
Example 2: Input: [7,6,4,3,1] Output: 0 Explanation: In this case, no transaction is done, i.e. max profit = 0.
class Solution { public int maxProfit(int[] prices) { if(prices.length == 0) return 0; int buy = prices[0]; int max = 0; for(int i = 1; i < prices.length; i++) { if(prices[i] < buy) //更改买入时间 buy = prices[i]; else { max = Math.max(max, prices[i] - buy); } } return max; } }给定一个未排序的整数数组,找出最长连续序列的长度。
要求算法的时间复杂度为 O(n)。
示例:
输入: [100, 4, 200, 1, 3, 2] 输出: 4 解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。
class Solution { public int longestConsecutive(int[] nums) { Set<Integer> set = new HashSet<Integer>(); for(Integer num : nums) { set.add(num); } int maxlen = 0; //对每个元素搜索set中与其相邻的所有元素,并移除 //(相当于一次移除了一整个连续子序列) for(Integer num : nums) { //如果set中有当前元素 if(set.remove(num)) { int curlen = 1; int cur = num; //当前元素向左搜索 while(set.remove(cur - 1)) { cur--; } curlen += num - cur; cur = num; //当前元素向右搜索 while(set.remove(cur + 1)) { cur++; } curlen += cur - num; //更新maxlen maxlen = Math.max(maxlen, curlen); } } return maxlen; } }给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。
例如,从根到叶子节点路径 1->2->3 代表数字 123。
计算从根到叶子节点生成的所有数字之和。
说明: 叶子节点是指没有子节点的节点。
示例 1: 输入: [1,2,3] 1 / \ 2 3 输出: 25 解释: 从根到叶子节点路径 1->2 代表数字 12. 从根到叶子节点路径 1->3 代表数字 13. 因此,数字总和 = 12 + 13 = 25.
示例 2: 输入: [4,9,0,5,1] 4 / \ 9 0 / \ 5 1 输出: 1026 解释: 从根到叶子节点路径 4->9->5 代表数字 495. 从根到叶子节点路径 4->9->1 代表数字 491. 从根到叶子节点路径 4->0 代表数字 40. 因此,数字总和 = 495 + 491 + 40 = 1026.
class Solution { public int sumNumbers(TreeNode root) { if(root == null) { return 0; } int[] sum = new int[1]; int cur = 0; preOrder(root, cur, sum); return sum[0]; } //前序遍历,因为子树需要当前val对cur的更新 //每到叶子节点就加到sum里 public void preOrder(TreeNode root, int cur, int[] sum) { if(root == null) { return; } //更新cur cur = cur * 10 + root.val; //叶子节点,加入sum if(root.left == null && root.right == null) { sum[0] += cur; return; } preOrder(root.left, cur, sum); preOrder(root.right, cur, sum); } }Given a non-empty array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
Example 1: Input: [2,2,1] Output: 1
Example 2: Input: [4,1,2,1,2] Output: 4
class Solution { //剑指offer做过,遍历一次位运算异或即可 public int singleNumber(int[] nums) { int x = 0; for(int i = 0; i < nums.length; i++){ x ^= nums[i]; } return x; } }给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的深拷贝。
/* class Node { public int val; public Node next; public Node random; public Node() {} public Node(int _val,Node _next,Node _random) { val = _val; next = _next; random = _random; } }; */ class Solution { //采用逐点复制插入原链表相应节点之后的方法,可以不需要额外空间 public Node copyRandomList(Node head) { if(head == null) { return null; } //头节点非空,先复制头节点为res Node res = new Node(head.val, null, null); res.next = head.next; head.next = res; //第一轮复制,先不考虑随机指针,每个复制的节点插入到原节点之后 for(Node p = res.next; p != null;) { Node p1 = new Node(p.val, null, null); p1.next = p.next; p.next = p1; p = p1.next; } //第二轮,连接随机指针,p1.random = p.random.next; for(Node p = head; p != null;) { Node p1 = p.next; if(p.random != null) { p1.random = p.random.next; } p = p1.next; } //最后取出复制的链表,并将原链表还原 head.next = res.next; for(Node p = res.next, p1 = res; p != null;) { p1.next = p.next; p1 = p1.next; p.next = p1.next; p = p.next; } return res; } }Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
Note:
The same word in the dictionary may be reused multiple times in the segmentation.You may assume the dictionary does not contain duplicate wordsExample 1: Input: s = "leetcode", wordDict = ["leet", "code"] Output: true Explanation: Return true because "leetcode" can be segmented as "leet code".
Example 2: Input: s = "applepenapple", wordDict = ["apple", "pen"] Output: true Explanation: Return true because "applepenapple" can be segmented as "apple pen apple". Note that you are allowed to reuse a dictionary word.
class Solution { public boolean wordBreak(String s, List<String> wordDict) { Set<Integer> invalidCutIndex = new HashSet<Integer>(); //记录无效切点 return dfs(s, 0, wordDict, invalidCutIndex); } //dfs只关心从切点i开始到结尾这部分是否能够成功切分 public boolean dfs(String s, int i, List<String> wordDict, Set<Integer> invalidCutIndex) { if(i == s.length()) return true; if(invalidCutIndex.contains(i)) return false; for(int cutIndex = i + 1; cutIndex < s.length() + 1; cutIndex++) { //切点处被切分到右半段 if(wordDict.contains(s.substring(i, cutIndex))) { //首先左半边要存在于单词表中 if(dfs(s, cutIndex, wordDict, invalidCutIndex)) return true; else invalidCutIndex.add(cutIndex); //无效的cutIndex } } invalidCutIndex.add(i); //无效的切点i return false; } }Given a linked list, determine if it has a cycle in it.
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Example 1:
Input: head = [3,2,0,-4], pos = 1 Output: true Explanation: There is a cycle in the linked list, where tail connects to the second node.
Example 2:
Input: head = [1,2], pos = 0 Output: true Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1 Output: false Explanation: There is no cycle in the linked list.
public class Solution { public boolean hasCycle(ListNode head) { if(head == null || head.next == null) //注意节点数小于两个的情况 return false; ListNode slow = head, fast = head.next; //初始值不相等 while(fast != null && slow != fast) { if(fast.next == null) break; fast = fast.next.next; slow = slow.next; } if(slow == fast) return true; else return false; } }Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Note: Do not modify the linked list.
Example 1:
Input: head = [3,2,0,-4], pos = 1 Output: tail connects to node index 1 Explanation: There is a cycle in the linked list, where tail connects to the second node.
Example 2:
Input: head = [1,2], pos = 0 Output: tail connects to node index 0 Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1 Output: no cycle Explanation: There is no cycle in the linked list.
public class Solution { //剑指offer做过 public ListNode EntryNodeOfLoop(ListNode pHead) { if(pHead == null) return null; else if(pHead.next == null) return null; ListNode fast = pHead, slow = pHead, start = pHead; while(fast != null) { if(fast.next != null) fast = fast.next.next; else fast = fast.next; //此时fast已经为null slow = slow.next; if(fast == slow) { //相等处fast多走了整数个环长,也是slow走的长度 while(start != slow) { //再走1个环外长度就刚好会遇到 start = start.next; slow = slow.next; } break; } } if(fast == null) //无环 return null; else return start; } }Sort a linked list in O(n log n) time using constant space complexity.
Example 1: Input: 4->2->1->3 Output: 1->2->3->4
Example 2: Input: -1->5->3->4->0 Output: -1->0->3->4->5
class Solution { public ListNode sortList(ListNode head) { if(head == null || head.next == null) return head; // 1.分成两半 ListNode prev = null, slow = head, fast = head; while(fast != null && fast.next != null) { prev = slow; slow = slow.next; fast = fast.next.next; } prev.next = null; // 2.分别排序 ListNode l1 = sortList(head); ListNode l2 = sortList(slow); // 3.合并l1和l2 return merge(l1, l2); } //合并两个升序链表 ListNode merge(ListNode l1, ListNode l2) { ListNode l = new ListNode(0), p = l; while(l1 != null && l2 != null) { if (l1.val < l2.val) { p.next = l1; l1 = l1.next; } else { p.next = l2; l2 = l2.next; } p = p.next; } if(l1 != null) p.next = l1; else p.next = l2; return l.next; } }Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.
Example 1: Input: [2,3,-2,4] Output: 6 Explanation: [2,3] has the largest product 6.
Example 2: Input: [-2,0,-1] Output: 0 Explanation: The result cannot be 2, because [-2,-1] is not a subarray.
class Solution { public int maxProduct(int[] nums) { int max = nums[0]; int curMax = nums[0], curMin = nums[0]; //每一位都计算包含当位数字的乘积最大值和最小值才行(负数使最大最小颠倒) for(int i = 1; i < nums.length; i++) { if(nums[i] < 0) { int temp = curMax; curMax = curMin; curMin = temp; } curMax = Math.max(nums[i], nums[i] * curMax); curMin = Math.min(nums[i], nums[i] * curMin); max = Math.max(max, curMax); } return max; } }Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.
You may assume that the array is non-empty and the majority element always exist in the array.
Example 1: Input: [3,2,3] Output: 3
Example 2: Input: [2,2,1,1,1,2,2] Output: 2
class Solution { public int majorityElement(int[] nums) { int major = nums[0]; int count = 1; //major元素多于一半,因此总会把count置为正 for(int i = 1; i < nums.length; i++) { if(count == 0) { //换新元素 major = nums[i]; count = 1; } else if(major == nums[i]) count++; else count--; } return major; } }You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
Example 1: Input: [1,2,3,1] Output: 4 Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3). Total amount you can rob = 1 + 3 = 4.
Example 2: Input: [2,7,9,3,1] Output: 12 Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1). Total amount you can rob = 2 + 9 + 1 = 12.
class Solution { public int rob(int[] nums) { //分别为是否包含当前元素的最大和 int sumNotContain = 0, sumContain = 0; for(int i = 0; i < nums.length; i++) { int temp = sumNotContain; sumNotContain = Math.max(sumNotContain, sumContain); //此时sumContain仍是包含上一个元素 sumContain = nums[i] + temp; } return Math.max(sumNotContain, sumContain); } }给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
示例 1: 输入: 11110 11010 11000 00000
输出: 1
示例 2: 输入: 11000 11000 00100 00011
输出: 3
class Solution { public int numIslands(char[][] grid) { int count = 0; for(int i = 0; i < grid.length; i++) { for(int j = 0; j < grid[i].length; j++) { //每发现一个island就dfsFill把整个island消除 if(grid[i][j] == '1') { count++; dfsFill(grid, i, j); } } } return count; } public void dfsFill(char[][] grid, int i, int j) { //return在前减少计算次数 if(i < 0 || i >= grid.length || j < 0 || j >= grid[i].length || grid[i][j] == '0') return; grid[i][j] = '0'; dfsFill(grid, i - 1, j); dfsFill(grid, i + 1, j); dfsFill(grid, i, j - 1); dfsFill(grid, i, j + 1); } }
