@Yano
2019-09-20T10:50:56.000000Z
字数 58138
阅读 11735
LeetCode
coding 笔记、点滴记录,以后的文章也会同步到公众号(Coding Insight)中,希望大家关注^_^
https://github.com/LjyYano/Thinking_in_Java_MindMapping
https://leetcode.com/problems/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.
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) {
if (nums == null || nums.length < 2)
return null;
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(target - nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
Integer v = map.get(nums[i]);
if (v != null && v != i) {
return new int[] { i, v };
}
}
return null;
}
}
https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/
Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution and you may not use the same element twice.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
class Solution {
public int[] twoSum(int[] nums, int target) {
if (nums == null || nums.length < 2)
return null;
int start = 0, end = nums.length - 1;
while(start < end) {
int sum = nums[start] + nums[end];
if(sum == target) return new int[]{start + 1, end + 1};
else if(sum < target) start++;
else end--;
}
return null;
}
}
https://leetcode.com/problems/3sum/
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.
Note: The solution set must not contain duplicate triplets.
For example, given array S = [-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>> ans = new ArrayList<>();
if(nums == null || nums.length < 3) return ans;
Set<List<Integer>> ansSet = new HashSet<>();
Arrays.sort(nums);
for(int l = 0; l <= nums.length - 3; l++) {
// 起始位置与前一个值相同,结果不会更多
if(l > 0 && nums[l] == nums[l - 1]) continue;
int m = l + 1, r = nums.length - 1, sum = -nums[l];
while(m < r) {
if(nums[m] + nums[r] > sum) {
r--;
} else if(nums[m] + nums[r] < sum) {
m++;
} else {
ansSet.add(Arrays.asList(nums[l], nums[m], nums[r]));
m++;
}
}
}
ans.addAll(ansSet);
return ans;
}
}
https://leetcode.com/problems/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).
class Solution {
public int threeSumClosest(int[] nums, int target) {
if(nums == null || nums.length < 3) return 0;
Arrays.sort(nums);
int minGap = Integer.MAX_VALUE;
int ans = 0;
for(int l = 0; l <= nums.length - 3; l++) {
// 起始位置与前一个值相同,结果不会更多
if(l > 0 && nums[l] == nums[l - 1]) continue;
for(int m = l + 1, r = nums.length - 1; m < r; ) {
int sum = nums[l] + nums[m] + nums[r];
int gap = Math.abs(target - sum);
if(gap < minGap) {
minGap = gap;
ans = sum;
}
if(sum == target) {
return target;
} else if(sum > target) {
r--;
} else {
m++;
}
}
}
return ans;
}
}
https://leetcode.com/problems/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.
Note: The solution set must not contain duplicate quadruplets.
For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.
A solution set is:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ans = new ArrayList<>();
if (nums == null || nums.length < 4)
return ans;
Set<List<Integer>> ansSet = new HashSet<>();
Arrays.sort(nums);
for (int i0 = 0; i0 <= nums.length - 4; i0++) {
// 结果不会更好
if (i0 > 0 && nums[i0] == nums[i0 - 1])
continue;
for (int i1 = i0 + 1; i1 <= nums.length - 3; i1++) {
int sum = target - nums[i0] - nums[i1];
int i2 = i1 + 1, i3 = nums.length - 1;
while (i2 < i3) {
if (nums[i2] + nums[i3] > sum) {
i3--;
} else if (nums[i2] + nums[i3] < sum) {
i2++;
} else {
ansSet.add(Arrays.asList(nums[i0], nums[i1], nums[i2], nums[i3]));
i2++;
}
}
}
}
ans.addAll(ansSet);
return ans;
}
}
https://leetcode.com/problems/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)).
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 A[], int m, int B[], int n) {
int total = m + n;
if(total & 0x1) return find_kth(A, m, B, n, total / 2 + 1);
else return (find_kth(A, m, B, n, total / 2)
+ find_kth(A, m, B, n, total / 2 + 1))/2.0;
}
private:
static int find_kth(int A[], int m, int B[], int n, int k){
//always assume that m is equal or smaller than n
if(m > n) return find_kth(B, n, A, m, k);
if(m == 0) return B[k-1];
if(k == 1) return min(A[0], B[0]);
//divide k into two parts
int ia = min(k / 2, m), ib = k - ia;
if (A[ia - 1] < B[ib - 1])
return find_kth(A + ia, m - ia, B, n, k - ia);
else if (A[ia - 1] > B[ib - 1])
return find_kth(A, m, B + ib, n - ib, k - ib);
else
return A[ia - 1];
}
};
https://leetcode.com/problems/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 class Solution {
public int maxArea(int[] nums) {
if(nums == null) return 0;
int ans = 0, start = 0, end = nums.length - 1;
while(start < end) {
int height = Math.min(nums[start], nums[end]);
ans = Math.max(ans, (end - start) * height);
if(nums[start] < nums[end]) {
// 没有必要判断start 与右边的桶了,因为短板在 start
start++;
} else {
end--;
}
}
return ans;
}
}
https://leetcode.com/problems/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.
The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!
class Solution {
public int trap(int[] height) {
if(height == null) return 0;
int ans = 0, maxLeft = 0, maxRight = 0;
int left = 0, right = height.length - 1;
while(left < right) {
// 左位置的左边的最高值,右位置的右边的最高值
maxLeft = Math.max(maxLeft, height[left]);
maxRight = Math.max(maxRight, height[right]);
if(maxLeft < maxRight) {
ans += maxLeft - height[left++];
} else {
ans += maxRight - height[right--];
}
}
return ans;
}
}
https://leetcode.com/problems/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 by modifying the input array in-place with O(1) extra memory.
Example:
Given 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.
class Solution {
public int removeDuplicates(int[] nums) {
if(nums == null || nums.length == 0) return 0;
int count = 0;
for(int i = 1; i < nums.length; i++) {
if(nums[i] != nums[count]) {
nums[++count] = nums[i];
}
}
return count + 1;
}
}
https://leetcode.com/problems/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.
class Solution {
public int removeDuplicates(int[] nums) {
if(nums == null || nums.length <= 2) return nums.length;
int count = 1;
for(int i = 2; i < nums.length; i++) {
if(nums[i] != nums[count] || (nums[i] == nums[count] && nums[i] != nums[count - 1])) {
nums[++count] = nums[i];
}
}
return count + 1;
}
}
https://leetcode.com/problems/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 by modifying the input array in-place with O(1) extra memory.
The order of elements can be changed. It doesn't matter what you leave beyond the new length.
Example:
Given nums = [3,2,2,3], val = 3,
Your function should return length = 2, with the first two elements of nums being 2.
class Solution {
public int removeElement(int[] nums, int val) {
if(nums == null || nums.length == 0) return 0;
int count = 0;
for(int i = 0; i < nums.length; i++) {
if(nums[i] != val) {
nums[count++] = nums[i];
}
}
return count;
}
}
https://leetcode.com/problems/next-permutation/
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
class Solution {
public void nextPermutation(int[] nums) {
// 1. 向前找首个递减
for (int i = nums.length - 2; i >= 0; i--) {
if (nums[i] < nums[i + 1]) {
int j = nums.length - 1;
// 2. 向前找首个大于nums[i]的索引
for (; j > i; j--) {
if (nums[j] > nums[i]) {
break;
}
}
// 3. 交换两个值
swap(nums, i, j);
// 4. 交换后面所有
reverseSwap(nums, i + 1, nums.length - 1);
return;
}
}
reverseSwap(nums, 0, nums.length - 1);
}
private void reverseSwap(int[] nums, int start, int end) {
while (start < end) {
swap(nums, start++, end--);
}
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
https://leetcode.com/problems/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.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
For example, given candidate set [2, 3, 6, 7] and target 7,
A solution set is:
[
[7],
[2, 2, 3]
]
class Solution {
public List<List<Integer>> combinationSum(int[] n, int target) {
List<List<Integer>> ans = new ArrayList<>();
if(n == null || n.length == 0) return ans;
Arrays.sort(n);
robot(n, 0, target, ans, new ArrayList<Integer>());
return ans;
}
private void robot(int[] n, int start, int left, List<List<Integer>> ans, List<Integer> tmp) {
if(left == 0) {
ans.add(new ArrayList<>(tmp));
return;
}
for(int i = start; i < n.length; i++) {
// 如果不符合条件,则循环后面可以省略
if(left >= n[i]) {
tmp.add(n[i]);
robot(n, i, left - n[i], ans, tmp);
tmp.remove(tmp.size() - 1);
} else {
break;
}
}
}
}
https://leetcode.com/problems/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.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
class Solution {
public List<List<Integer>> combinationSum2(int[] n, int target) {
List<List<Integer>> ans = new ArrayList<>();
if(n == null || n.length == 0) return ans;
Arrays.sort(n);
Set<List<Integer>> ansSet = new HashSet<>();
robot(n, 0, target, ansSet, new ArrayList<Integer>());
ans.addAll(ansSet);
return ans;
}
private void robot(int[] n, int start, int left, Set<List<Integer>> ansSet, List<Integer> tmp) {
if(left == 0) {
ansSet.add(new ArrayList<>(tmp));
return;
}
for(int i = start; i < n.length; i++) {
// 如果不符合条件,则循环后面可以省略
if(left >= n[i]) {
tmp.add(n[i]);
robot(n, i + 1, left - n[i], ansSet, tmp);
tmp.remove(tmp.size() - 1);
} else {
break;
}
}
}
}
https://leetcode.com/problems/combination-sum-iii/
Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.
Example 1:
Input: k = 3, n = 7
Output:
[[1,2,4]]
Example 2:
Input: k = 3, n = 9
Output:
[[1,2,6], [1,3,5], [2,3,4]]
Credits:Special thanks to @mithmatt for adding this problem and creating all test cases.
class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> ans = new ArrayList<>();
robot(1, k, n, ans, new ArrayList<Integer>());
return ans;
}
private void robot(int start, int k, int left, List<List<Integer>> ans, List<Integer> tmp) {
if(k < 0 || left < 0) return;
if(k == 0 && left == 0) {
ans.add(new ArrayList<>(tmp));
return;
}
for(int i = start; i <= 9; i++) {
if(left >= i && k > 0) {
tmp.add(i);
robot(i + 1, k - 1, left - i, ans, tmp);
tmp.remove(tmp.size() - 1);
} else {
return;
}
}
}
}
https://leetcode.com/problems/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.
class Solution {
public int search(int[] nums, int target) {
if(nums == null) return -1;
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[mid]) {
if(target >= nums[start] && target < nums[mid]) {
end = mid - 1;
} else {
start = mid + 1;
}
}
// 右序列连续递增
if(nums[mid] <= nums[end]) {
if(target > nums[mid] && target <= nums[end]) {
start = mid + 1;
} else {
end = mid - 1;
}
}
}
return -1;
}
}
https://leetcode.com/problems/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?
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).
Write a function to determine if a given target is in the array.
The array may contain duplicates.
public class Solution {
public boolean search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target)
return true;
if (nums[left] < nums[mid]) {
if (target <= nums[mid] && target >= nums[left])
right = mid - 1;
else
left = mid + 1;
} else if (nums[left] > nums[mid]) {
if (target >= nums[left] || target <= nums[mid])
right = mid - 1;
else
left = mid + 1;
} else
left++;
}
return false;
}
}
https://leetcode.com/problems/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].
class Solution {
public int[] searchRange(int[] nums, int target) {
if(nums == null) return new int[] {-1, -1};
// 先找到一个位置
int start = 0, end = nums.length - 1, ans = -1;
while(start <= end) {
int mid = (start + end) / 2;
if(nums[mid] == target) {
ans = mid;
break;
}
if(nums[mid] < target) {
start = mid + 1;
} else {
end = mid - 1;
}
}
if(ans == -1) return new int[] {-1, -1};
// 找起始点
int s = ans, e = ans;
while(s >= 0 && nums[s] == target) {
s--;
}
while(e < nums.length && nums[e] == target) {
e++;
}
return new int[] {s + 1, e - 1};
}
}
https://leetcode.com/problems/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.
Example 1:
Input: [1,3,5,6], 5
Output: 2
Example 2:
Input: [1,3,5,6], 2
Output: 1
Example 3:
Input: [1,3,5,6], 7
Output: 4
Example 1:
Input: [1,3,5,6], 0
Output: 0
class Solution {
public int searchInsert(int[] nums, int target) {
if(nums == null) return 0;
// 先找到一个位置
int start = 0, end = nums.length - 1, ans = -1;
while(start <= end) {
int mid = (start + end) / 2;
if(nums[mid] == target) {
ans = mid;
break;
}
if(nums[mid] < target) {
start = mid + 1;
} else {
end = mid - 1;
}
}
if(ans != -1) return ans;
// start 和 end 已经包含了插入的信息
return start > end ? start : end;
}
}
https://leetcode.com/problems/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.
class Solution {
public int firstMissingPositive(int[] n) {
if(n == null) return 0;
for(int i = 0; i < n.length; i++) {
while(n[i] > 0 && n[i] <= n.length && n[i] != n[n[i] - 1]) {
swap(n, i, n[i] - 1);
}
}
// 遍历,找出n[i] != i + 1的结果
for(int i = 0; i < n.length; i++) {
if(n[i] != i + 1) return i + 1;
}
return n.length + 1;
}
private void swap(int[] n, int a, int b) {
int tmp = n[a];
n[a] = n[b];
n[b] = tmp;
}
}
https://leetcode.com/problems/jump-game/
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.
For example:
A = [2,3,1,1,4], return true.
A = [3,2,1,0,4], return false.
class Solution {
public boolean canJump(int[] nums) {
if(nums == null || nums.length <= 1) return true;
// farest[i] 表示[0, i]能跳到的最远位置
int[] farest = new int[nums.length];
farest[0] = nums[0];
for(int i = 1; i < nums.length; i++) {
// 若前面断档,则后面无解
if(farest[i - 1] == i - 1) break;
farest[i] = Math.max(farest[i - 1], nums[i] + i);
}
return farest[nums.length - 1] != 0;
}
}
https://leetcode.com/problems/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.)
Note:
You can assume that you can always reach the last index.
public class Solution {
public int jump(int[] nums) {
if (nums.length <= 1) return 0;
int reach = nums[0];
int lastreach = 0;
int step = 0;
for (int i = 1; i <= reach && i < nums.length; i++) {
if (i > lastreach) {
step++;
lastreach = reach;
}
reach = Math.max(reach, i + nums[i]);
}
if (reach < nums.length - 1) return 0;
return step;
}
}
https://leetcode.com/problems/rotate-image/
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) {
if(matrix == null || matrix[0] == null || matrix.length != matrix[0].length) return;
int n = matrix.length;
// 中轴互换
for(int i = 0; i < n / 2; i++) {
for(int j = 0; j < n; j++) {
swap(matrix, i, j, n - i - 1, j);
}
}
// 正对角线互换
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
swap(matrix, i, j, j, i);
}
}
}
private void swap(int[][] matrix, int x0, int y0, int x1, int y1) {
int tmp = matrix[x0][y0];
matrix[x0][y0] = matrix[x1][y1];
matrix[x1][y1] = tmp;
}
}
https://leetcode.com/problems/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.
click to show more practice.
More practice:
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 == null) return 0;
// 数组可省略
int[] result = new int[nums.length];
int max = nums[0];
result[0] = nums[0];
for(int i = 1; i < nums.length; i++) {
// f(i + 1) = max(f(i) + n[i + 1], n[i + 1])
result[i] = Math.max(nums[i] + result[i - 1], nums[i]);
max = Math.max(max, result[i]);
}
return max;
}
}
https://leetcode.com/problems/spiral-matrix/
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].
public class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new ArrayList<Integer>();
if (matrix == null || matrix.length == 0) {
return result;
}
int startx = 0, endx = matrix.length - 1;
int starty = 0, endy = matrix[0].length - 1;
while (startx <= endx && starty <= endy) {
for (int y = starty; y <= endy; y++) {
result.add(matrix[startx][y]);
}
for (int x = startx + 1; x <= endx; x++) {
result.add(matrix[x][endy]);
}
if (startx == endx || starty == endy) {
break;
}
for (int y = endy - 1; y >= starty; y--) {
result.add(matrix[endx][y]);
}
for (int x = endx - 1; x >= startx + 1; x--) {
result.add(matrix[x][starty]);
}
startx++;
starty++;
endx--;
endy--;
}
return result;
}
}
https://leetcode.com/problems/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 ]
]
public class Solution {
public int[][] generateMatrix(int n) {
if (n <= 0) {
return new int[0][0];
}
int[][] matrix = new int[n][n];
int num = 1;
int startx = 0, endx = n - 1;
int starty = 0, endy = n - 1;
while (startx <= endx && starty <= endy) {
for (int y = starty; y <= endy; y++) {
matrix[startx][y] = num++;
}
for (int x = startx + 1; x <= endx; x++) {
matrix[x][endy] = num++;
}
if (startx == endx || starty == endy) {
break;
}
for (int y = endy - 1; y >= starty; y--) {
matrix[endx][y] = num++;
}
for (int x = endx - 1; x >= startx + 1; x--) {
matrix[x][starty] = num++;
}
startx++;
starty++;
endx--;
endy--;
}
return matrix;
}
}
https://leetcode.com/problems/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].
/**
* Definition for an interval.
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
class Solution {
public List<Interval> merge(List<Interval> intervals) {
List<Interval> ans = new ArrayList<>();
if (intervals == null || intervals.size() == 0) {
return ans;
}
// sort by start
Collections.sort(intervals, new Comparator<Interval>() {
@Override
public int compare(Interval o1, Interval o2) {
return o1.start != o2.start ? o1.start - o2.start : o1.end - o2.end;
}
});
Interval o1 = intervals.get(0);
for(int i = 1; i < intervals.size(); i++) {
Interval o2 = intervals.get(i);
if (o1.end >= o2.start) {
o1 = new Interval(o1.start, Math.max(o1.end, o2.end));
} else {
ans.add(o1);
o1 = o2;
}
}
ans.add(o1);
return ans;
}
}
https://leetcode.com/problems/insert-interval/
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.
Example 1:
Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9].
Example 2:
Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1,2],[3,10],[12,16].
This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].
/**
* Definition for an interval.
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
class Solution {
public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
List<Interval> result = new ArrayList<>();
int i = 0;
// add all the intervals ending before newInterval starts
while (i < intervals.size() && intervals.get(i).end < newInterval.start)
result.add(intervals.get(i++));
// merge all overlapping intervals to one considering newInterval
while (i < intervals.size() && intervals.get(i).start <= newInterval.end) {
newInterval = new Interval( // we could mutate newInterval here also
Math.min(newInterval.start, intervals.get(i).start),
Math.max(newInterval.end, intervals.get(i).end));
i++;
}
result.add(newInterval); // add the union of intervals we got
// add all the rest
while (i < intervals.size())
result.add(intervals.get(i++));
return result;
}
}
https://leetcode.com/problems/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?
Above is a 3 x 7 grid. How many possible unique paths are there?
Note: m and n will be at most 100.
class Solution {
public int uniquePaths(int m, int n) {
// 可以优化成一维数组
int[][] dp = new int[m][n];
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
if(i == 0 || j == 0) {
dp[i][j] = 1;
} else {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
}
return dp[m - 1][n - 1];
}
}
https://leetcode.com/problems/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]
]
The total number of unique paths is 2.
Note: m and n will be at most 100.
class Solution {
public int uniquePathsWithObstacles(int[][] grid) {
if(grid == null || grid.length == 0 ) return 0;
int m = grid.length, n = grid[0].length;
int[][] dp = new int[m][n];
// 初始化行
for(int i = 0; i < n; i++) {
if(grid[0][i] == 1) break;
dp[0][i] = 1;
}
// 初始化列
for(int i = 0; i < m; i++) {
if(grid[i][0] == 1) break;
dp[i][0] = 1;
}
for(int i = 1; i < m; i++) {
for(int j = 1; j < n; j++) {
if(grid[i][j] == 1) {
dp[i][j] = 0;
} else {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
}
return dp[m - 1][n - 1];
}
}
https://leetcode.com/problems/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.
Example 1:
[[1,3,1],
[1,5,1],
[4,2,1]]
Given the above grid map, return 7. Because the path 1→3→1→1→1 minimizes the sum.
class Solution {
public int minPathSum(int[][] grid) {
if(grid == null || grid.length == 0 ) return 0;
int m = grid.length, n = grid[0].length;
int[][] dp = new int[m][n];
dp[0][0] = grid[0][0];
// 初始化行
for(int i = 1; i < n; i++) {
dp[0][i] = grid[0][i] + dp[0][i - 1];
}
// 初始化列
for(int i = 1; i < m; i++) {
dp[i][0] = grid[i][0] + dp[i - 1][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];
}
}
https://leetcode.com/problems/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.
public class Solution {
public int[] plusOne(int[] digits) {
if (digits == null || digits.length == 0) {
return null;
}
int[] reslut = new int[digits.length + 1];
digits[digits.length - 1]++;
for (int i = digits.length - 1; i >= 0; i--) {
reslut[i + 1] += digits[i];
reslut[i] += reslut[i + 1] / 10;
reslut[i + 1] %= 10;
}
if (reslut[0] == 0) {
return Arrays.copyOfRange(reslut, 1, reslut.length);
} else {
return reslut;
}
}
}
https://leetcode.com/problems/set-matrix-zeroes/
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?
public class Solution {
public void setZeroes(int[][] matrix) {
if (matrix == null || matrix.length == 0) {
return;
}
int mx = matrix.length;
int my = matrix[0].length;
boolean xflag = false, yflag = false;
for (int i = 0; i < mx; i++) {
if (matrix[i][0] == 0) {
xflag = true;
break;
}
}
for (int i = 0; i < my; i++) {
if (matrix[0][i] == 0) {
yflag = true;
break;
}
}
for (int i = 1; i < mx; i++) {
for (int j = 1; j < my; j++) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
for (int i = 1; i < mx; i++) {
if (matrix[i][0] == 0) {
for (int j = 0; j < my; j++) {
matrix[i][j] = 0;
}
}
}
for (int i = 0; i < my; i++) {
if (matrix[0][i] == 0) {
for (int j = 0; j < mx; j++) {
matrix[j][i] = 0;
}
}
}
if (xflag) {
for (int i = 0; i < mx; i++) {
matrix[i][0] = 0;
}
}
if (yflag) {
for (int i = 0; i < my; i++) {
matrix[0][i] = 0;
}
}
}
}
https://leetcode.com/problems/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.
Note:
You are not suppose to use the library's sort function for this problem.
click to show follow up.
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 an one-pass algorithm using only constant space?
class Solution {
public void sortColors(int[] nums) {
int start = 0, end = nums.length - 1;
for(int i = 0; i <= end; i++) {
// 顺序不能换,因为i后面可能换到0,但是i前面是不可能有2的
while(nums[i] == 2 && i < end) swap(nums, i, end--);
while(nums[i] == 0 && i > start) swap(nums, i, start++);
}
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
https://leetcode.com/problems/subsets/
Given a set of distinct integers, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,3], a solution is:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
if(nums == null) return ans;
robot(0, nums, ans, new ArrayList<Integer>());
return ans;
}
private void robot(int start, int[] nums, List<List<Integer>> ans, List<Integer> tmp) {
ans.add(new ArrayList(tmp));
for(int i = start; i < nums.length; i++) {
tmp.add(nums[i]);
robot(i + 1, nums, ans, tmp);
tmp.remove(tmp.size() - 1);
}
}
}
https://leetcode.com/problems/subsets-ii/
Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).
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],
[]
]
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
Set<List<Integer>> ansSet = new HashSet<>();
Arrays.sort(nums); // 先排序
robot(0, nums, ansSet, new ArrayList<Integer>());
ans.addAll(ansSet);
return ans;
}
private void robot(int start, int[] nums, Set<List<Integer>> ans, List<Integer> tmp) {
ans.add(new ArrayList(tmp));
for(int i = start; i < nums.length; i++) {
tmp.add(nums[i]);
robot(i + 1, nums, ans, tmp);
tmp.remove(tmp.size() - 1);
}
}
}
https://leetcode.com/problems/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.
For example,
Given board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
word = "ABCCED", -> returns true,
word = "SEE", -> returns true,
word = "ABCB", -> returns false.
public class Solution {
public static boolean exist(char[][] board, String word) {
if (board == null || board[0].length == 0 || board.length == 0
|| word == null) {
return false;
}
int rows = board.length;
int cols = board[0].length;
boolean[] visited = new boolean[rows * cols];
int pathLength = 0;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
if (dfs(board, rows, cols, row, col, word, pathLength, visited)) {
return true;
}
}
}
return false;
}
public static boolean dfs(char[][] board, int rows, int cols, int row,
int col, String word, int pathLength, boolean[] visited) {
if (pathLength == word.length()) {
return true;
}
boolean hasPath = false;
if (row >= 0 && row < rows && col >= 0 && col < cols
&& board[row][col] == word.charAt(pathLength)
&& !visited[row * cols + col]) {
pathLength++;
visited[row * cols + col] = true;
hasPath = dfs(board, rows, cols, row, col - 1, word, pathLength,
visited)
|| dfs(board, rows, cols, row - 1, col, word, pathLength,
visited)
|| dfs(board, rows, cols, row, col + 1, word, pathLength,
visited)
|| dfs(board, rows, cols, row + 1, col, word, pathLength,
visited);
if (!hasPath) {
pathLength--;
visited[row * cols + col] = false;
}
}
return hasPath;
}
}
https://leetcode.com/problems/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.
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].
The largest rectangle is shown in the shaded area, which has area = 10 unit.
For example,
Given heights = [2,1,5,6,2,3],
return 10.
class Solution {
public int largestRectangleArea(int[] A) {
int area = 0;
for (int i = 0; i < A.length; i++) {
// 每找到局部峰值,向前遍历数组
if(i + 1 < A.length && A[i + 1] >= A[i]) continue;
int min = A[i];
for (int j = i; j >= 0; j--) {
min = Math.min(min, A[j]);
area = Math.max(area, (i + 1 - j) * min);
}
}
return area;
}
}
https://leetcode.com/problems/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.
class Solution {
public int maximalRectangle(char[][] matrix) {
if(matrix == null || matrix.length == 0 || matrix[0].length == 0) return 0;
int m = matrix.length, n = matrix[0].length;
int[][] height = new int[m][n];
// height[i][j] 表示第i行j列的1的高度
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
if(matrix[i][j] == '1') {
height[i][j] = (i >= 1 ? height[i - 1][j] : 0) + 1;
}
}
}
int area = 0;
for(int i = 0; i < m; i++) {
area = Math.max(area, largestRectangleArea(height[i]));
}
return area;
}
public int largestRectangleArea(int[] A) {
int area = 0;
for (int i = 0; i < A.length; i++) {
// 每找到局部峰值,向前遍历数组
if(i + 1 < A.length && A[i + 1] >= A[i]) continue;
int min = A[i];
for (int j = i; j >= 0; j--) {
min = Math.min(min, A[j]);
area = Math.max(area, (i + 1 - j) * min);
}
}
return area;
}
}
https://leetcode.com/problems/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.
class Solution {
public void merge(int[] A, int m, int[] B, int n) {
int i = m - 1, j = n - 1, end = m + n - 1;
while(i >= 0 && j >= 0) {
if(A[i] > B[j]) A[end--] = A[i--];
else A[end--] = B[j--];
}
while(j >= 0) A[end--] = B[j--];
}
}
https://leetcode.com/problems/pascals-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]
]
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> ans = new ArrayList<>();
if(numRows <= 0) return ans;
int count = 0;
while(count < numRows) {
List<Integer> last = count > 0 ? ans.get(count - 1) : new ArrayList<>();
List<Integer> tmp = new ArrayList();
for(int i = 0; i <= count; i++) {
if(i == 0 || i == count) tmp.add(1);
else tmp.add(last.get(i - 1) + last.get(i));
}
ans.add(tmp);
count++;
}
return ans;
}
}
https://leetcode.com/problems/pascals-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].
Note:
Could you optimize your algorithm to use only O(k) extra space?
class Solution {
public List<Integer> getRow(int rowIndex) {
List<Integer> tmp = new ArrayList<>();
if(rowIndex < 0) return tmp;
List<Integer> pre = new ArrayList<>();
int k = 0;
while(k <= rowIndex) {
for(int i = 0; i <= k; i++) {
if(i == 0 || i == k) tmp.add(1);
else tmp.add(pre.get(i - 1) + pre.get(i));
}
pre = new ArrayList(tmp);
tmp.clear();
k++;
}
return pre;
}
}
https://leetcode.com/problems/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).
Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int k = triangle.size();
if(k == 0) return 0;
List<Integer> pre = triangle.get(0);
List<Integer> ans = new ArrayList<>();
for(int i = 1; i < triangle.size(); i++) {
List<Integer> now = triangle.get(i);
for(int j = 0; j < now.size(); j++) {
if(j == 0) ans.add(now.get(j) + pre.get(0));
else if(j == now.size() - 1) ans.add(now.get(j) + pre.get(j - 1));
else ans.add(now.get(j) + Math.min(pre.get(j), pre.get(j - 1)));
}
pre = new ArrayList(ans);
ans.clear();
}
return Collections.min(pre);
}
}
https://leetcode.com/problems/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.
Example 1:
Input: [7, 1, 5, 3, 6, 4]
Output: 5
max. difference = 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
In this case, no transaction is done, i.e. max profit = 0.
class Solution {
public int maxProfit(int[] prices) {
int maxProfit = 0;
// 存储从prices[0..i]的最小值
int lowest = Integer.MAX_VALUE;
for (int v : prices) {
lowest = Math.min(v, lowest);
maxProfit = Math.max(maxProfit, v - lowest);
}
return maxProfit;
}
}
https://leetcode.com/problems/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).
class Solution {
public int maxProfit(int[] prices) {
// 只要有利润就卖,就是最优解。
int profit = 0;
for(int i = 1; i < prices.length; i++) {
if(prices[i] > prices[i - 1]) {
profit += prices[i] - prices[i - 1];
}
}
return profit;
}
}
https://leetcode.com/problems/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.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
class Solution {
public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}
int n = prices.length;
/**
* l[i][j]: 第i天可进行j次交易,且最后一次交易在最后一天卖出
* g[i][j]: 第i天最多j次交易的最大利润
*
* l[i][j] = max(l[i-1][j], g[i-1][j-1]) + diff
* g[i][j] = max(l[i][j], g[i-1][j])
*
* l[i][j](最后一次交易在最后一天卖出)公式分2种情况:
* 1. l[i-1][j] + diff:最后一次交易在i-1天卖出,加上diff相当于i-1天没卖,最后一天卖,不增加交易次数
* 2. g[i-1][j-1] + diff: i-1天卖出,结果不会比1好;i-1天未卖出,则可以卖,增加交易次数
*
* 可以转化为一维数组 int[3]
*/
int[][] l = new int[n][3];
int[][] g = new int[n][3];
for (int i = 1; i < n; i++) {
int diff = prices[i] - prices[i - 1];
for (int j = 1; j <= 2; j++) {
l[i][j] = Math.max(l[i - 1][j], g[i - 1][j - 1]) + diff;
g[i][j] = Math.max(l[i][j], g[i - 1][j]);
}
}
return g[n - 1][4];
}
}
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/
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 k transactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
class Solution {
public int maxProfit(int k, int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}
if(k >= prices.length) return maxProfit(prices);
int n = prices.length;
int[] l = new int[k + 1];
int[] g = new int[k + 1];
for (int i = 1; i < n; i++) {
int diff = prices[i] - prices[i - 1];
for (int j = k; j >= 1; j--) {
l[j] = Math.max(l[j], g[j - 1]) + diff;
g[j] = Math.max(l[j], g[j]);
}
}
return g[k];
}
public int maxProfit(int[] prices) {
// 只要有利润就卖,就是最优解。
int profit = 0;
for(int i = 1; i < prices.length; i++) {
if(prices[i] > prices[i - 1]) {
profit += prices[i] - prices[i - 1];
}
}
return profit;
}
}
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/
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) with the following restrictions:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day)
Example:
prices = [1, 2, 3, 0, 2]
maxProfit = 3
transactions = [buy, sell, cooldown, buy, sell]
class Solution {
public int maxProfit(int[] prices) {
if(prices == null || prices.length == 0) return 0;
int n = prices.length;
// buy[i] 表示第i天持有股票,最大利润
int[] buy = new int[n];
// sell[i] 表示第i天为持股,最大利润
int[] sell = new int[n];
buy[0] = -prices[0];
sell[0] = 0;
for(int i = 1; i < n; i++) {
buy[i] = Math.max(buy[i - 1], (i > 1 ? sell[i - 2] : 0) - prices[i]);
sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i]);
}
return sell[n - 1];
}
}
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/description/
Your are given an array of integers prices, for which the i-th element is the price of a given stock on day i; and a non-negative integer fee representing a transaction fee.
You may complete as many transactions as you like, but you need to pay the transaction fee for each transaction. You may not buy more than 1 share of a stock at a time (ie. you must sell the stock share before you buy again.)
Return the maximum profit you can make.
Example 1:
Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
Output: 8
Explanation: The maximum profit can be achieved by:
Buying at prices[0] = 1
Selling at prices[3] = 8
Buying at prices[4] = 4
Selling at prices[5] = 9
The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
Note:
0 < prices.length <= 50000.
0 < prices[i] < 50000.
0 <= fee < 50000.
class Solution {
public int maxProfit(int[] prices, int fee) {
if(prices == null || prices.length == 0) return 0;
int n = prices.length;
// buy[i] 表示第i天持有股票,最大利润
int[] buy = new int[n];
// sell[i] 表示第i天为持股,最大利润
int[] sell = new int[n];
buy[0] = -prices[0];
sell[0] = 0;
for(int i = 1; i < n; i++) {
buy[i] = Math.max(buy[i - 1], sell[i - 1] - prices[i]);
sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i] - fee);
}
return sell[n - 1];
}
}
https://leetcode.com/problems/longest-consecutive-sequence/
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.
class Solution {
public int longestConsecutive(int[] nums) {
if(nums == null || nums.length == 0) return 0;
Map<Integer, Integer> map = new HashMap<>();
int ans = 0;
for(int i = 0; i < nums.length; i++) {
if(!map.containsKey(nums[i])) {
int left = map.containsKey(nums[i] - 1) ? map.get(nums[i] - 1) : 0;
int right = map.containsKey(nums[i] + 1) ? map.get(nums[i] + 1) : 0;
int times = left + right + 1;
map.put(nums[i], times);
ans = Math.max(ans, times);
map.put(nums[i] - left, times);
map.put(nums[i] + right, times);
}
}
return ans;
}
}
https://leetcode.com/problems/maximum-product-subarray/
Find the contiguous subarray within an array (containing at least one number) which has the largest product.
For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.
class Solution {
public int maxProduct(int[] nums) {
int maxLocal = nums[0];
int minLocal = nums[0];
int global = nums[0];
for(int i = 1; i < nums.length; i++) {
int temp = maxLocal;
maxLocal = Math.max(Math.max(nums[i] * temp, nums[i] * minLocal), nums[i]);
minLocal = Math.min(Math.min(nums[i] * temp, nums[i] * minLocal), nums[i]);
global = Math.max(global, maxLocal);
}
return global;
}
}
https://leetcode.com/problems/find-minimum-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).
Find the minimum element.
You may assume no duplicate exists in the array.
public class Solution {
public int findMin(int[] nums) {
if (nums.length == 1) {
return nums[0];
}
if (nums.length == 2) {
return Math.min(nums[0], nums[1]);
}
int s = 0, e = nums.length - 1;
int m = (s + e) / 2;
if (nums[s] < nums[e]) {
return nums[s];
}
if (nums[m] > nums[s]) {
return findMin(Arrays.copyOfRange(nums, m + 1, e + 1));
}
return findMin(Arrays.copyOfRange(nums, s, m + 1));
}
}
https://leetcode.com/problems/find-peak-element/
A peak element is an element that is greater than its neighbors.
Given an input array where num[i] ≠ num[i+1], find a peak element and return its index.
The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.
You may imagine that num[-1] = num[n] = -∞.
For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.
click to show spoilers.
Note:
Your solution should be in logarithmic complexity.
Credits:Special thanks to @ts for adding this problem and creating all test cases.
class Solution {
public int findPeakElement(int[] nums) {
if(nums == null || nums.length == 0) return 0;
for(int i = 0; i < nums.length; i++) {
boolean left = i == 0 ? true : nums[i] > nums[i - 1];
boolean right = i == nums.length - 1 ? true : nums[i] > nums[i + 1];
if(left && right) return i;
}
return 0;
}
}
https://leetcode.com/problems/majority-element/
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.
Credits:Special thanks to @ts for adding this problem and creating all test cases.
class Solution {
public int majorityElement(int[] nums) {
if(nums == null || nums.length == 0) return 0;
int count = 0, ans = 0;
for(int v : nums) {
if(count == 0) {
ans = v;
count = 1;
} else if(v != ans) {
count--;
} else {
count++;
}
}
return ans;
}
}
https://leetcode.com/problems/majority-element-ii/
Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.
class Solution {
public List<Integer> majorityElement(int[] nums) {
List<Integer> ans = new ArrayList<>();
if(nums == null || nums.length == 0) return ans;
int n1 = 0, n2 = 0, c1 = 0, c2 = 0;
for(int v : nums) {
if(v == n1) c1++;
else if(v == n2) c2++;
else if(c1 == 0) {
c1 = 1;
n1 = v;
}
else if(c2 == 0) {
c2 = 1;
n2 = v;
}
else {
c1--;
c2--;
}
}
c1 = 0; c2 = 0;
for(int v : nums) {
if(v == n1) c1++;
else if(v == n2) c2++;
}
if(c1 > nums.length / 3) ans.add(n1);
if(c2 > nums.length / 3) ans.add(n2);
return ans;
}
}
https://leetcode.com/problems/rotate-array/
Rotate an array of n elements to the right by k steps.
For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
Note:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
[show hint]
Hint:
Could you do it in-place with O(1) extra space?
Related problem: Reverse Words in a String II
Credits:Special thanks to @Freezen for adding this problem and creating all test cases.
public class Solution { static void reverse(int[] nums, int st, int ed) {
while (st < ed) {
int t = nums[st];
nums[st] = nums[ed];
nums[ed] = t;
st++;
ed--;
}
}
public static void rotate(int[] nums, int k) {
int length = nums.length;
k = k % length;
if (length == 1 || k == 0)
return;
reverse(nums, 0, length - k - 1);
reverse(nums, length - k, length - 1);
reverse(nums, 0, length - 1);
}}
https://leetcode.com/problems/minimum-size-subarray-sum/
Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead.
For example, given the array [2,3,1,2,4,3] and s = 7,
the subarray [4,3] has the minimal length under the problem constraint.
click to show more practice.
More practice:
If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).
Credits:Special thanks to @Freezen for adding this problem and creating all test cases.
class Solution {
public int minSubArrayLen(int s, int[] nums) {
if(nums == null || nums.length == 0) return 0;
int start = 0, end = 0, sum = 0, ans = Integer.MAX_VALUE;
while(end < nums.length && start < nums.length) {
// 滑动窗口,end
while(end < nums.length && sum < s) {
sum += nums[end++];
if(sum >= s) {
ans = Math.min(ans, end - start);
}
}
// 滑动窗口,start
while(start < nums.length && sum >= s) {
sum -= nums[start++];
if(sum < s) {
ans = Math.min(ans, end - start + 1);
}
}
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
}
https://leetcode.com/problems/contains-duplicate/
Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.
class Solution {
public boolean containsDuplicate(int[] nums) {
if(nums == null || nums.length == 0) return false;
Set<Integer> set = new HashSet<>();
for(int v : nums) {
if(set.contains(v)) return true;
set.add(v);
}
return false;
}
}
https://leetcode.com/problems/contains-duplicate-ii/
Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
if(nums == null || nums.length == 0) return false;
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++) {
if(map.containsKey(nums[i]) && i - map.get(nums[i]) <= k) {
return true;
} else {
map.put(nums[i], i);
}
}
return false;
}
}
https://leetcode.com/problems/product-of-array-except-self/
Given an array of n integers where n > 1, nums, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].
Solve it without division and in O(n).
For example, given [1,2,3,4], return [24,12,8,6].
Follow up:
Could you solve it with constant space complexity? (Note: The output array does not count as extra space for the purpose of space complexity analysis.)
class Solution {
public int[] productExceptSelf(int[] nums) {
final int[] left = new int[nums.length];
left[0] = 1;
for(int i = 1; i < nums.length; i++) {
left[i] = nums[i - 1] * left[i - 1];
}
int right = 1;
for(int i = nums.length - 1; i >= 0; i--) {
left[i] *= right;
right *= nums[i];
}
return left;
}
}
https://leetcode.com/problems/missing-number/
Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array.
Example 1
Input: [3,0,1]
Output: 2
Example 2
Input: [9,6,4,2,3,5,7,0,1]
Output: 8
Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?
Credits:Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
class Solution {
public int missingNumber(int[] nums) {
if(nums == null) return 0;
int sum = (1 + nums.length) * nums.length / 2;
for(int v : nums) {
sum -= v;
}
return sum;
}
}
https://leetcode.com/problems/move-zeroes/
Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.
For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0].
Note:
You must do this in-place without making a copy of the array.
Minimize the total number of operations.
Credits:Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
public class Solution {
public void moveZeroes(int[] nums) {
int t = 0;
// 把非0元素移到前面
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
nums[t++] = nums[i];
}
}
// 把后面元素值0
for (int i = t; i < nums.length; i++) {
nums[i] = 0;
}
}
}
https://leetcode.com/problems/find-the-duplicate-number/
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
Note:
You must not modify the array (assume the array is read only).
You must use only constant, O(1) extra space.
Your runtime complexity should be less than O(n2).
There is only one duplicate number in the array, but it could be repeated more than once.
Credits:Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
public class Solution {
// https://segmentfault.com/a/1190000003817671
public int findDuplicate(int[] nums) {
int slow = 0;
int fast = 0;
// 找到快慢指针相遇的地方
do{
slow = nums[slow];
fast = nums[nums[fast]];
} while(slow != fast);
int find = 0;
// 用一个新指针从头开始,直到和慢指针相遇
while(find != slow){
slow = nums[slow];
find = nums[find];
}
return find;
}
}
https://leetcode.com/problems/find-all-duplicates-in-an-array/
Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements that appear twice in this array.
Could you do it without extra space and in O(n) runtime?
Example:
Input:
[4,3,2,7,8,2,3,1]
Output:
[2,3]
class Solution {
public List<Integer> findDuplicates(int[] nums) {
List<Integer> ans = new ArrayList<>();
for(int i = 0; i < nums.length; i++) {
if(nums[i] != nums[nums[i] - 1]) {
swap(nums, i, nums[i] - 1);
i--;
}
}
System.out.println(Arrays.toString(nums));
for(int i = 0; i < nums.length; i++) {
if(nums[i] != i + 1) {
ans.add(nums[i]);
}
}
return ans;
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
https://leetcode.com/problems/game-of-life/
According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970."
Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):
Write a function to compute the next state (after one update) of the board given its current state.
Follow up:
Could you solve it in-place? Remember that the board needs to be updated at the same time: You cannot update some cells first and then use their updated values to update other cells.
In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems?
Credits:Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
class Solution {
public void gameOfLife(int[][] board) {
final int m = board.length;
final int n = board[0].length;
/**
状态0:死细胞转为死细胞
状态1:活细胞转为活细胞
状态2:活细胞转为死细胞
状态3:死细胞转为活细胞
**/
// encode
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int live = countLive(board, i, j); // number of live cells
if (board[i][j] == 0 && live == 3) {
board[i][j] = 3;
} else if (board[i][j] == 1 && (live < 2 || live > 3)) {
board[i][j] = 2;
}
}
}
// decode
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
board[i][j] %= 2;
}
}
}
private int countLive(int[][] nums, int i, int j) {
int count = 0;
int m = nums.length, n = nums[0].length;
for(int x = i - 1; x <= i + 1; x++) {
for(int y = j - 1; y <= j + 1; y++) {
if(x == i && y == j) continue;
if(x >= 0 && x < m && y >= 0 && y < n && (nums[x][y] == 1 || nums[x][y] == 2)) {
count++;
}
}
}
return count;
}
}
https://leetcode.com/problems/insert-delete-getrandom-o1/
Design a data structure that supports all following operations in average O(1) time.
Example:
// Init an empty set.
RandomizedSet randomSet = new RandomizedSet();
// Inserts 1 to the set. Returns true as 1 was inserted successfully.
randomSet.insert(1);
// Returns false as 2 does not exist in the set.
randomSet.remove(2);
// Inserts 2 to the set, returns true. Set now contains [1,2].
randomSet.insert(2);
// getRandom should return either 1 or 2 randomly.
randomSet.getRandom();
// Removes 1 from the set, returns true. Set now contains [2].
randomSet.remove(1);
// 2 was already in the set, so return false.
randomSet.insert(2);
// Since 2 is the only number in the set, getRandom always return 2.
randomSet.getRandom();
class RandomizedSet {
private List<Integer> list;
private Map<Integer, Integer> map;
private Random random;
/** Initialize your data structure here. */
public RandomizedSet() {
list = new ArrayList<>();
map = new HashMap<>();
random = new Random();
}
/**
* Inserts a value to the set. Returns true if the set did not already contain
* the specified element.
*/
public boolean insert(int val) {
if (map.containsKey(val)) {
return false;
}
list.add(val);
map.put(val, list.size() - 1);
return true;
}
/**
* Removes a value from the set. Returns true if the set contained the specified
* element.
*/
public boolean remove(int val) {
if (!map.containsKey(val)) {
return false;
}
int index = map.get(val);
list.set(index, list.get(list.size() - 1));
map.put(list.get(index), index);
map.remove(val);
list.remove(list.size() - 1);
return true;
}
/** Get a random element from the set. */
public int getRandom() {
if (list.size() == 0) {
return 0;
}
return list.get(random.nextInt(list.size()));
}
}
https://leetcode.com/problems/insert-delete-getrandom-o1-duplicates-allowed/
Design a data structure that supports all following operations in average O(1) time.
Note: Duplicate elements are allowed.
Example:
// Init an empty collection.
RandomizedCollection collection = new RandomizedCollection();
// Inserts 1 to the collection. Returns true as the collection did not contain 1.
collection.insert(1);
// Inserts another 1 to the collection. Returns false as the collection contained 1. Collection now contains [1,1].
collection.insert(1);
// Inserts 2 to the collection, returns true. Collection now contains [1,1,2].
collection.insert(2);
// getRandom should return 1 with the probability 2/3, and returns 2 with the probability 1/3.
collection.getRandom();
// Removes 1 from the collection, returns true. Collection now contains [1,2].
collection.remove(1);
// getRandom should return 1 and 2 both equally likely.
collection.getRandom();
class RandomizedCollection {
private List<Integer> list;
private Map<Integer, Set<Integer>> map;
private Random random;
/** Initialize your data structure here. */
public RandomizedCollection() {
list = new ArrayList<>();
map = new HashMap<>();
random = new Random();
}
/**
* Inserts a value to the set. Returns true if the set did not already contain
* the specified element.
*/
public boolean insert(int val) {
boolean flag = false;
if (!map.containsKey(val)) {
flag = true;
map.put(val, new HashSet<Integer>());
}
map.get(val).add(list.size());
list.add(val);
return flag;
}
/**
* Removes a value from the set. Returns true if the set contained the specified
* element.
*/
public boolean remove(int val) {
if (!map.containsKey(val)) {
return false;
}
int removed = map.get(val).iterator().next();
map.get(val).remove(removed);
if (removed < list.size() - 1) {
Integer tail = list.get(list.size() - 1);
list.set(removed, tail);
map.get(tail).remove(list.size() - 1);
map.get(tail).add(removed);
}
list.remove(list.size() - 1);
if (map.get(val).size() == 0) {
map.remove(val);
}
return true;
}
/** Get a random element from the set. */
public int getRandom() {
if (list.size() == 0) {
return 0;
}
return list.get(random.nextInt(list.size()));
}
}
/**
* Your RandomizedCollection object will be instantiated and called as such:
* RandomizedCollection obj = new RandomizedCollection();
* boolean param_1 = obj.insert(val);
* boolean param_2 = obj.remove(val);
* int param_3 = obj.getRandom();
*/
https://leetcode.com/problems/third-maximum-number/
Given a non-empty array of integers, return the third maximum number in this array. If it does not exist, return the maximum number. The time complexity must be in O(n).
Example 1:
Input: [3, 2, 1]
Output: 1
Explanation: The third maximum is 1.
Example 2:
Input: [1, 2]
Output: 2
Explanation: The third maximum does not exist, so the maximum (2) is returned instead.
Example 3:
Input: [2, 2, 3, 1]
Output: 1
Explanation: Note that the third maximum here means the third maximum distinct number.
Both numbers with value 2 are both considered as second maximum.
class Solution {
public int thirdMax(int[] nums) {
long max0 = Long.MIN_VALUE;
long max1 = Long.MIN_VALUE;
long max2 = Long.MIN_VALUE;
for(int v : nums) {
if(max0 < v) {
max2 = max1;
max1 = max0;
max0 = (long)v;
} else if(max1 < v && v < max0) {
max2 = max1;
max1 = (long)v;
} else if(max2 < v && v < max1){
max2 = (long)v;
}
}
return (int) (max2 == Long.MIN_VALUE ? max0 : max2);
}
}
https://leetcode.com/problems/max-consecutive-ones/
Given a binary array, find the maximum number of consecutive 1s in this array.
Example 1:
Input: [1,1,0,1,1,1]
Output: 3
Explanation: The first two digits or the last three digits are consecutive 1s.
The maximum number of consecutive 1s is 3.
Note:
The input array will only contain 0 and 1.
The length of input array is a positive integer and will not exceed 10,000
class Solution {
public int findMaxConsecutiveOnes(int[] nums) {
int ans = 0;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 1) {
int count = 0;
while(i < nums.length && nums[i] == 1) {
count++;
i++;
}
ans = Math.max(ans, count);
}
}
return ans;
}
}