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.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
思路:用一个HashMap来存储已经遍历过的元素及其下标,然后用target减去正在遍历的元素,判断HashMap中是否存在这个数,若存在,则找到答案。
public class Solution {
public int[] twoSum(int[] nums, int target) {
if(nums == null) return null;
int[] ret = new int[2];
Map map = new HashMap<>();
for(int i=0;iif(map.containsKey(target-nums[i])) {
ret[0] = map.get(target-nums[i]);
ret[1] = i;
return ret;
}
map.put(nums[i], i);
}
return ret;
}
}
和上一题类似,只不过数组升序排列。
思路:当然可以用上面那道题的方法来做,但是显然我们没有利用排序信息。可以使用两个指针,这样不用额外的HashMap的O(n) 的空间复杂度。时间复杂度仍是O(N)。
public class Solution {
public int[] twoSum(int[] numbers, int target) {
if(numbers == null) return null;
int start = 0, end = numbers.length - 1;
int[] ret = new int[2];
while(start < end) {
int sum = numbers[start] + numbers[end];
if(sum == target) {
ret[0] = start+1;
ret[1] = end+1;
return ret;
}
else if(sum > target) {
end --;
}
else {
start ++;
}
}
return ret;
}
}
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.
思路:数组排序,然后对排序后不重复的每个数作为可能三元组的第一个数,然后剩余的数用两个指针,找two sum,同时注意去重。
public class Solution {
public List> threeSum(int[] nums) {
Arrays.sort(nums);
List> ret = new ArrayList<>();
for(int i=0; i2; i++) {
if(i == 0 || (i > 0 && nums[i] != nums[i-1])) { // 去重
int low = i+1, high = nums.length-1, sum = - nums[i];
while(low < high) {
if(nums[low] + nums[high] == sum) {
ret.add(Arrays.asList(nums[i], nums[low], nums[high]));
while(low < high && nums[low] == nums[low+1]) low++; // 去重
while(low < high && nums[high] == nums[high-1]) high--; // 去重
low++;
high--;
}
else if(nums[low] + nums[high] < sum) {
low++;
}
else
high--;
}
}
}
return ret;
}
}
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
思路:二分查找的方法。具体看leetcode solution最高票解释。核心思想就是理解中位数的定义,中位数就是把一个数组分成左右长度相同的两部分,并且一部分中的所有数都大于另一部分的所有数。短串中的下标为i,长串中的下标为(m+n+1)-i,目标就是找到i和j,是a[i-1] <= b[j] && b[j-1] <= a[i]。而这步搜索的过程又可以用二分来加速。
public class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
// nums1表示短串,nums2表示长串
if(nums1.length > nums2.length) {
return helper(nums2, nums1);
}
return helper(nums1, nums2);
}
private double helper(int[] nums1, int[] nums2) {
int m = nums1.length, n = nums2.length;
if(n == 0)
return 0.0;
int iMin = 0, iMax = m, i = 0, j = 0, halfLen = (m + n + 1) / 2;
while(iMin <= iMax) {
i = (iMax + iMin) / 2;
j = halfLen - i;
if(i < m && nums2[j-1] > nums1[i]) iMin = i + 1;
else if(i > 0 && nums1[i-1] > nums2[j]) iMax = i - 1;
else {
int maxLeft = 0;
if(i == 0) maxLeft = nums2[j-1];
else if(j == 0) maxLeft = nums1[i-1];
else maxLeft = Math.max(nums1[i-1], nums2[j-1]);
if((m+n) % 2 == 1) return maxLeft * 1.0;
int minRight = 0;
if(i == m ) minRight = nums2[j];
else if(j == n) minRight = nums1[i];
else minRight = Math.min(nums1[i], nums2[j]);
return (maxLeft + minRight) / 2.0;
}
}
return 0.0;
}
}
Given an array of integers and an integer k, you need to find the number of unique k-diff pairs in the array. Here a k-diff pair is defined as an integer pair (i, j), where i and j are both numbers in the array and their absolute difference is k.
思路:用一个hashMap来存储每个元素及其出现的次数,遍历所有key,K=0的情况特殊考虑,只考虑v2=v1+k的情况的话就不用删除已遍历元素,因为v2=v1-k的情况就相当于v1=v2+k。
public class Solution {
public int findPairs(int[] nums, int k) {
if (nums == null || nums.length == 0 || k < 0) return 0;
Map map = new HashMap<>();
int count = 0;
for (int i : nums) {
map.put(i, map.getOrDefault(i, 0) + 1);
}
for (Map.Entry entry : map.entrySet()) {
if (k == 0) {
//count how many elements in the array that appear more than twice.
if (entry.getValue() >= 2) {
count++;
}
} else {
if (map.containsKey(entry.getKey() + k)) {
count++;
}
}
}
return count;
}
}
Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this in place with constant memory.
For example,
Given input array nums = [1,1,2],
Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. It doesn’t matter what you leave beyond the new length.
思路:三个指针,pos,pre,cur,pos始终指向当前应该被替换的位置。最后pos就是不重复元素的个数。
public class Solution {
public int removeDuplicates(int[] nums) {
if(nums.length == 0) {
return 0;
}
int p1=0, pos=1, p2 = 1;
while(p2 != nums.length) {
if(nums[p1] != nums[p2]) {
nums[pos] = nums[p2];
pos++;
}
p1++;
p2++;
}
return pos;
}
}
Given an array and a value, remove all instances of that value in place and return the new length.
Do not allocate extra space for another array, you must do this in place with constant memory.
The order of elements can be changed. It doesn’t matter what you leave beyond the new length.
解法1:两个指针,一首一尾,注意边界条件,避免大量无用交换。该方法会改变顺序。
public class Solution {
public int removeElement(int[] nums, int val) {
int p1 = 0;
int p2 = nums.length - 1;
while(p2 >= p1) {
if(nums[p1] == val) {
if(nums[p2] != val) {
nums[p1] = nums[p2];
nums[p2] = val;
p1 ++;
p2 --;
}
else if(nums[p2] == val) {
p2 --;
}
}
else
p1 ++;
}
return p1;
}
}
解法2:方法代码很简洁,一个指针指向始终待填充的坑,另一个从头到尾遍历,当符合条件时就把元素填入坑中,坑移动一个。这个方法不改变顺序。
public class Solution {
public int removeElement(int[] A, int elem) {
int m = 0;
for(int i = 0; i < A.length; i++){
if(A[i] != elem){
A[m] = A[i];
m++;
}
}
return m;
}
}
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.
思路:动态规划。The maximum sum in the first i elements is either the maximum sum in the first i - 1 elements (which we’ll call MaxSoFar), or it is that of a subvector that ends in position i (which we’ll call MaxEndingHere). MaxEndingHere is either A[i] plus the previous MaxEndingHere, or just A[i], whichever is larger.
public class Solution {
public int maxSubArray(int[] nums) {
if(nums == null || nums.length == 0) return Integer.MIN_VALUE;
int maxSoFar = nums[0], maxEndingHere = nums[0];
for(int i=1;ireturn maxSoFar;
}
}
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.
思路:动态规划。但是由于相乘会负负得正,所以必须保留以i结尾的最小值。
public class Solution {
boolean isInputValid = true;
public int maxProduct(int[] nums) {
if(nums == null || nums.length == 0) {
isInputValid = false;
return 0;
}
int maxEndingHere, minEndingHere; // i
int maxHerePre = nums[0], minHerePre = nums[0]; // i-1
int maxSoFar = nums[0];
for(int i=1;ireturn maxSoFar;
}
}
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.
思路:动态规划 sum[i][j] = Math.min(sum[i-1][j], sum[i][j-1]) + grid[i][j];
public class Solution {
public int minPathSum(int[][] grid) {
if(grid == null) return 0;
int row = grid.length;
if(row == 0) return 0;
int column = grid[0].length;
int[][] sum = new int[row][column];
sum[0][0] = grid[0][0];
for(int i=1;i0] = sum[i-1][0] + grid[i][0];
}
for(int j=1;j0][j] = sum[0][j-1] + grid[0][j];
}
for(int i=1;ifor(int j=1;j1][j], sum[i][j-1]) + grid[i][j];
}
}
return sum[row-1][column-1];
}
}
Given an array of n positive integers and a positive integer s, find the minimal length of a 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.
思路:两个指针,先移动后一个使和大于s,记录长度,再保持大于s的前提下移动前一个指针,记录最小长度。复杂度O(N)
public class Solution {
public int minSubArrayLen(int s, int[] nums) {
if(nums == null || nums.length == 0) return 0;
int ahead = 0, min = Integer.MAX_VALUE, sum = 0;
for(int behind=0;behindwhile(sum >= s) {
min = Math.min(min, behind-ahead+1);
sum -= nums[ahead++];
}
}
return min == Integer.MAX_VALUE ? 0 : min;
}
}
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.
思路:只有所有位都是9的时候才会产生最高位的进位。
public int[] plusOne(int[] digits) {
int n = digits.length;
for(int i=n-1; i>=0; i--) {
if(digits[i] < 9) {
digits[i]++;
return digits;
}
digits[i] = 0;
}
int[] newNumber = new int [n+1];
newNumber[0] = 1;
return newNumber;
}
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.
思路:对于连续的gram组成的区域,面积等于这些gram的最小值乘以gram的个数。如果该区域左边的gram比这个最小值大,那么可以把这个gram加入进来扩大面积,右边也是类似。所以这个问题关键是找到以数组中每个数为最小值的区域的最大面积。暴力的做法是O(n^2),借助栈,可以把复杂度降到O(n)。
public class Solution {
public int largestRectangleArea(int[] heights) {
Deque stack = new LinkedList<>();
int maxArea = 0;
for(int i=0; i<=heights.length; i++) {
int h = (i == heights.length ? 0 : heights[i]);
if(stack.peek() == null || h >= heights[stack.peek()]) {
stack.push(i);
}
else {
int iTop = stack.pop();
maxArea = Math.max(maxArea, heights[iTop] * (stack.peek() == null ? i : i - 1 - stack.peek()));
i--;
}
}
return maxArea;
}
}
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.
思路:从后往前归并
public class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int n1=m-1, n2=n-1, count = m + n - 1;
while(n1 >= 0 && n2 >= 0) {
if(nums1[n1] > nums2[n2]) {
nums1[count] = nums1[n1];
n1 --;
}
else {
nums1[count] = nums2[n2];
n2 --;
}
count --;
}
while(n2>=0) {
nums1[count] = nums2[n2];
count --;
n2 --;
}
}
}
Given preorder and inorder traversal of a tree, construct the binary tree.
思路:由前序确定根节点,由中序确定左右子树,递归。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder == null || inorder == null || preorder.length == 0 || inorder.length == 0) return null;
return helper(preorder, 0, preorder.length-1, inorder, 0, inorder.length-1);
}
private TreeNode helper(int[] preorder, int pStart, int pEnd, int[] inorder, int iStart, int iEnd) {
if(pStart > pEnd || iStart > iEnd) return null;
TreeNode root = new TreeNode(preorder[pStart]);
int i = iStart;
while(i <= iEnd){
if(inorder[i] == root.val)
break;
i++;
}
root.left = helper(preorder, pStart+1, pStart+i-iStart, inorder, iStart, i-1);
root.right = helper(preorder, pStart+1+i-iStart, pEnd, inorder, i+1, iEnd);
return root;
}
}
Given inorder and postorder traversal of a tree, construct the binary tree.
思路:后序确定根节点,由中序确定左右子树。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(inorder == null || postorder == null) return null;
return helper(inorder, postorder, 0, inorder.length-1, 0, postorder.length-1);
}
private TreeNode helper(int[] inorder, int[] postorder, int instart, int inend, int poststart, int postend) {
if(instart > inend || poststart > postend) return null;
int rootVal = postorder[postend];
TreeNode root = new TreeNode(rootVal);
int inRootIndex = instart;
for(int i=instart;i<=inend;i++) {
if(inorder[i] == rootVal) {
inRootIndex = i;
break;
}
}
root.left = helper(inorder, postorder, instart, inRootIndex-1, poststart, poststart+inRootIndex-instart-1);
root.right = helper(inorder, postorder, inRootIndex+1, inend, poststart+inRootIndex-instart, postend-1);
return root;
}
}
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]
]
public class Solution {
public List> generate(int numRows) {
List> pascal = new ArrayList<>();
for(int i=1;i<=numRows;i++) {
if(i == 1) {
List list = new ArrayList<>();
list.add(1);
pascal.add(list);
continue;
}
if(i == 2) {
List list = new ArrayList<>();
list.add(1);
list.add(1);
pascal.add(list);
continue;
}
List list = new ArrayList<>();
for(int j=0;jif(j == 0) {
list.add(1);
continue;
}
if(j == i-1) {
list.add(1);
break;
}
list.add(pascal.get(i-2).get(j-1) + pascal.get(i-2).get(j));
}
pascal.add(list);
}
return pascal;
}
}
Given an index k, return the kth row of the Pascal’s triangle.
For example, given k = 3,
Return [1,3,3,1].
思路:利用上一层的结果原地计算下一层,但是在覆盖上一层的数的时候要保存有用的那个数。
public class Solution {
public List getRow(int rowIndex) {
List result = new ArrayList<>();
if(rowIndex == 0) {
result.add(1);
return result;
}
if(rowIndex == 1) {
result.add(1);
result.add(1);
return result;
}
int tmp = 1;
int addTmp;
result.add(1);
result.add(1);
for(int i=2;i<=rowIndex;i++) {
for(int j=1;j1);
}
return result;
}
}
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.
思路:Moore voting algorithm。设定一个变量count,依次遍历数组的元素,若count为0,则设主要元素为当前数,并count+1;若当前数等于当前主要元素,则count+1;若不等,则count-1。根据定义可知主要元素的个数比其他所有数的个数之和还多。所以最后的当前主要元素就是主要元素。
public class Solution {
public int majorityElement(int[] nums) {
int major = nums[0], count = 0;
for(int num : nums) {
if(count == 0) {
count ++;
major = num;
}
else if(num == major)
count ++;
else
count --;
}
return major;
}
}
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].
思路:左右分别反向后再整体反向。
public class Solution {
public void rotate(int[] nums, int k) {
int n = nums.length;
k = k % n;
if(n == 1 || n == 0)
return;
reverse(nums, 0, n - k - 1);
reverse(nums, n - k, n - 1);
reverse(nums, 0, n - 1);
}
private void reverse(int[] nums, int i, int j) {
int tmp;
while(i < j) {
tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
i++;
j--;
}
}
}
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) {
int left = 0, right = nums.length - 1;
while(left < right) {
int mid = (left + right) / 2;
if(nums[mid] > nums[right]) {
left = mid+1;
}
else {
right = mid;
}
}
return nums[left];
}
}
Follow up for “Find Minimum in Rotated Sorted Array”:
What if duplicates are allowed?
public class Solution {
public int findMin(int[] nums) {
int left = 0, right = nums.length - 1;
while(left < right) {
int mid = (left + right) / 2;
if(nums[mid] > nums[right])
left = mid + 1;
else if (nums[mid] < nums[right])
right = mid;
else
right--;
}
return nums[left];
}
}
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.
思路:主要是把情况想清楚,左边有序,右边有序,在有序段之内,不在有序段之内。
public class Solution {
public int search(int[] nums, int target) {
if(nums == null) return -1;
int left = 0, right = nums.length-1, mid;
while(left <= right) {
mid = (left + right) >> 1;
if(nums[mid] == target) return mid;
if(nums[left] <= nums[mid]) {
if(target >= nums[left] && target < nums[mid])
right = mid - 1;
else
left = mid + 1;
}
else {
if(target > nums[mid] && target <= nums[right])
left = mid + 1;
else
right = mid - 1;
}
}
return -1;
}
}
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.
思路:由于存在重复,对于nums[left] == nums[right] == nums[mid]的情况我们无法处理,这个时候只能够去除一个元素。同时,判断左边是否有序,我们不能仅靠左边小于中间来判断,因为可能出现相等的情况,所以需要用中间大于右边说明右边乱序进而说明左边有序来辅助判断。右边是否有序也是类似。
public class Solution {
public boolean search(int[] nums, int target) {
if(nums == null) return false;
int left = 0, right = nums.length - 1, mid;
while(left <= right) {
mid = (left + right) >> 1;
if(target == nums[mid]) return true;
if(nums[left] < nums[mid] || nums[mid] > nums[right]) {
if(target >= nums[left] && target < nums[mid])
right = mid - 1;
else
left = mid + 1;
}
else if(nums[mid] < nums[right] || nums[left] > nums[mid]) {
if(target > nums[mid] && target <= nums[right])
left = mid + 1;
else
right = mid - 1;
}
else {
right--;
}
}
return false;
}
}
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.
解法1:暴力时间O(n^2),空间O(1)
解法2:先排序再比较相邻元素是否相等。时间O(nlogn),空间O(1)。
解法3:hashSet。时间O(n),空间O(n)。
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.
思路:遍历数组,用一个set保存刚刚遍历过的k个元素。
public class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
Set appearedNum = new HashSet<> ();
for(int i=0;iif(!appearedNum.contains(nums[i])) {
appearedNum.add(nums[i]);
}
else
return true;
if(i >= k) {
appearedNum.remove(nums[i-k]);
}
}
return false;
}
}
Given a sorted integer array without duplicates, return the summary of its ranges.
For example, given [0,1,2,4,5,7], return [“0->2”,”4->5”,”7”].
思路:遍历数组元素,找到连续部分的首和尾,再判断首尾是否相等分两种情况存入list中。
public class Solution {
public List summaryRanges(int[] nums) {
List ret = new ArrayList<> ();
if(nums == null) return ret;
for(int i=0;iint start = nums[i];
while(i+1 < nums.length && nums[i+1] - nums[i] == 1)
i++;
if(nums[i] != start)
ret.add(start + "->" + nums[i]);
else
ret.add(start + "");
}
return ret;
}
}
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].
思路:每个output[i]位置的数等于(i前面的元素相乘)再乘上(i后面的元素相乘),所以可以通过两遍遍历数组得到结果,一遍正向,一遍反向。
public class Solution {
public int[] productExceptSelf(int[] nums) {
if(nums == null || nums.length == 0) return null;
int[] output = new int[nums.length];
output[0] = 1;
for(int i=1; i1] * output[i-1];
}
int tmp = nums[nums.length-1];
for(int j=nums.length-2; j>=0; j--) {
output[j] = tmp * output[j];
tmp *= nums[j];
}
return output;
}
}
Given an array containing n distinct numbers taken from 0, 1, 2, …, n, find the one that is missing from the array.
For example,
Given nums = [0, 1, 3] return 2.
Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?
解法1:
遍历然后用数组下标来表示数字,用数组里的数的状态表示是否出现过,在这个解法中状态是是否大于nums.length+1。
public class Solution {
public int missingNumber(int[] nums) {
if(nums == null) return -1;
int nP1 = nums.length + 1;
for(int num : nums) {
int index = Math.abs(num) % nP1;
if(index == nums.length)
continue;
else if(nums[index] < nP1) {
nums[index] += nP1;
}
}
int ret = nums.length;
for(int i=0;iif(nums[i] <= nums.length)
ret = i;
}
return ret;
}
}
解法2:
下标和数组里的数同时异或
public class Solution {
public int missingNumber(int[] nums) {
if(nums == null) return -1;
int ret = nums.length;
for(int i=0;ireturn ret;
}
}
解法3:
二分查找,但使用此方法最好是数组已排好序。若数组中的数字一个都没缺失,那么下标和数字应该相等。
public int missingNumber(int[] nums) { //binary search
Arrays.sort(nums);
int left = 0, right = nums.length, mid= (left + right)/2;
while(left2;
if(nums[mid]>mid) right = mid;
else left = mid+1;
}
return left;
}
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?
思路:和Missing Number的一种做法类似,由于限定了元素的范围在下标范围之内,所以可以把元素和下标联合起来。用某个下标下的数的状态来表示和下标相同的数的出现情况。此处采用的正负状态来区分。
public class Solution {
public List findDuplicates(int[] nums) {
if(nums == null) return null;
List duplicates = new ArrayList();
for(int i=0;iint index = Math.abs(nums[i]) - 1;
if(nums[index] > 0)
nums[index] = -nums[index];
else
duplicates.add(index + 1);
}
return duplicates;
}
}
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.
思路:和上题思路差不多,利用下标。
public class Solution {
public List findDisappearedNumbers(int[] nums) {
if(nums == null) return null;
for(int i=0;iint index = Math.abs(nums[i])-1;
if(nums[index] > 0)
nums[index] = -nums[index];
}
List disappearedNumbers = new ArrayList();
for(int i=0;iif(nums[i]>0) {
disappearedNumbers.add(i+1);
}
}
return disappearedNumbers;
}
}
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:
1、You must do this in-place without making a copy of the array.
2、Minimize the total number of operations.
思路:移动非零元素到前面,剩余位置填0.
// Shift non-zero values as far forward as possible
// Fill remaining space with zeros
public void moveZeroes(int[] nums) {
if (nums == null || nums.length == 0) return;
int insertPos = 0;
for (int num: nums) {
if (num != 0) nums[insertPos++] = num;
}
while (insertPos < nums.length) {
nums[insertPos++] = 0;
}
}
题目: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).
解法1:
最多四次遍历,分别找出最大值,最小值,次大值,第三大值。
public class Solution {
public int thirdMax(int[] nums) {
int max = nums[0];
for(int i=1;iif(nums[i] > max) max = nums[i];
}
int min = nums[0];
for(int i=1;iif(nums[i] < min) min = nums[i];
}
if(max == min) return max;
int secondMax = min;
for(int i=0;iif(nums[i] < max && nums[i] > secondMax)
secondMax = nums[i];
}
if(secondMax == min) return max;
int thirdMax = min;
for(int i=0;iif(nums[i] < secondMax && nums[i] > thirdMax)
thirdMax = nums[i];
}
return thirdMax;
}
}
解法2:
用set来对数组去重,用优先队列来保持前三大的数。
public class Solution {
public int thirdMax(int[] nums) {
PriorityQueue pq = new PriorityQueue<>();
Set s = new HashSet<>();
for(int num : nums) {
if(!s.contains(num)) {
s.add(num);
pq.add(num);
if(s.size() > 3) {
s.remove(pq.poll());
}
}
}
if(s.size() < 3) {
while(pq.size() != 1) {
pq.poll();
}
}
return pq.peek();
}
}
Given a 2d grid map of ‘1’s (land) and ‘0’s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
思路:遍历,遇到1就开始用DFS清除与其相连的1,并把岛屿的数量加1。
public class Solution {
private int n;
private int m;
public int numIslands(char[][] grid) {
if(grid == null) return 0;
n = grid.length;
if(n == 0) return 0;
m = grid[0].length;
int count = 0;
for(int i=0; ifor(int j=0; jif(grid[i][j] == '1') {
DFSMarking(grid, i, j);
count++;
}
}
}
return count;
}
public void DFSMarking(char[][] grid, int i, int j) {
if(i<0 || j<0 || i>=n || j>=m || grid[i][j] != '1') return;
grid[i][j] = '0';
DFSMarking(grid, i-1, j);
DFSMarking(grid, i+1, j);
DFSMarking(grid, i, j-1);
DFSMarking(grid, i, j+1);
}
}
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
Integers in each row are sorted from left to right.
The first integer of each row is greater than the last integer of the previous row.
For example,
Consider the following matrix:
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
Given target = 3, return true.
思路:直接当成一个排序的list二分查找做即可
public class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int row_num = matrix.length;
if(row_num==0) return false;
int col_num = matrix[0].length;
int begin = 0, end = row_num * col_num - 1;
while(begin <= end){
int mid = (begin + end) / 2;
int mid_value = matrix[mid/col_num][mid%col_num];
if( mid_value == target){
return true;
}else if(mid_value < target){
//Should move a bit further, otherwise dead loop.
begin = mid+1;
}else{
end = mid-1;
}
}
return false;
}
}