Remove Duplicates from Sorted Array

思路:两个指针,头指针在0,尾指针从1开始寻找,找到第一个不等于头指针值的数,覆盖掉头指针后面那个数,然后尾指针往后移。

public int removeDuplicates(int[] nums) {
if(nums.length <= 1) return nums.length;
int i = 0;
for(int j = 1; j < nums.length; j++){
if(nums[i] != nums[j]){
nums[++i] = nums[j];
}
}
return i + 1;
} 这种解法具有普遍性,具体看下一题
public int removeDuplicates(int[] nums) {
if(nums == null) return 0;
int i = 0;
int j = 0;
while(j < nums.length){
if(i < 1 || nums[i - 1] != nums[j]){
nums[i] = nums[j];
i++;
}
j++;
}
return i;
}

Remove Duplicates from Sorted ArrayII

思路:同样使用两个指针,都从1开始,同时加上一个标志位,用于区分两个数重复还是多余两个数重复,可分为三种情况

当前数和前一个数不等,则尾指针覆盖掉头指针,两个指针都后移,标志位置为1;

当前数和前一个数相等且标志位为1,则尾指针覆盖掉头指针,两个指针都后移,标志位置为0;

当前数和前一个数相等且标志位为0,则尾指针后移

public int removeDuplicates(int[] nums) {
if(nums.length == 0) return 0;
int count = 1;
boolean flag = true;
for(int i = 1; i < nums.length; i++){
if(nums[i] == nums[i - 1] && flag){
nums[count] = nums[i];
count++;
flag = false;
}
else if(nums[i] == nums[i - 1] && !flag){
continue;
}
else{
nums[count] = nums[i];
count++;
flag = true;
}
}
return count;
} public int removeDuplicates(int[] nums) {
if(nums == null) return 0;
int i = 0;
int j = 0;
while(j < nums.length){
if(i < 2 || nums[j] != nums[i - 2]){
nums[i] = nums[j];
i++;
}
j++;
}
return i;
}

Best Time to Buy and Sell Stock

思路:dp[i]为第i天的最大利润,则dp[i] = max(dp[i - 1],prices[i] - min_Buy)

public int maxProfit(int[] prices) {
if(prices.length == 0) return 0;
int profit = 0;
int min_buy = prices[0];
for(int i = 1; i < prices.length; i++){
min_buy = Math.min(min_buy,prices[i]);
profit = Math.max(profit,(prices[i] - min_buy));
}
return profit;
}

Best Time to Buy and Sell StockII

思路:比较后一天和前一天的价格,只要后一天的贵,则选择买进

public int maxProfit(int[] prices) {
if(prices.length <= 1) return 0;
int res = 0; for(int i = 1; i < prices.length; i++){
if(prices[i] > prices[i - 1]){
res += (prices[i] - prices[i - 1]);
}
}
return res;
}

Best Time to Buy and Sell StockIII

思路:dp[i]为在第i天前进行一次交易,第i天后进行一次交易得的总利润,即dp[i] = preProfit[i] + postProfit[i],preProfit[i]和postProfit[i]的算法和题1一样

public int maxProfit(int[] prices) {
int n = prices.length;
if(n < 2) return 0;
int[] preProfit = new int[n];
int[] postProfit = new int[n]; //计算第i天之前交易一次获得的最大利益
int curMin = prices[0];
preProfit[0] = 0;
for(int i = 1; i < n; i++){
curMin = Math.min(curMin,prices[i]);
preProfit[i] = Math.max(preProfit[i - 1],prices[i] - curMin);
} //计算第i天之后交易一次获得的最大利益
int curMax = prices[n - 1];
postProfit[n - 1] = 0;
for(int i = n - 2; i >= 0; i--){
curMax = Math.max(prices[i],curMax);
postProfit[i] = Math.max(postProfit[i + 1],curMax - prices[i]);
} int max = Integer.MIN_VALUE;
for(int i = 0; i < n; i++){
max = Math.max(max,preProfit[i] + postProfit[i]);
}
return max;
}

Game of Life

思路:将题目中四个条件标记为四个状态即:

活细胞周围有少于两个活细胞,则死亡 状态2

活细胞周围有超过3个活细胞,则死亡 状态3

活细胞周围有两个或三个活细胞,则继续存活 状态4

死细胞周围有三个活细胞,则存活 状态5

判断细胞周围的活细胞数目,即周围标记为1 2 3 4的都是活细胞,标记完以后,根据状态判断细胞是存活还是死亡,即状态4 5存活

public void gameOfLife(int[][] board) {
int m = board.length;
if(m == 0) return;
int n = board[0].length; for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(board[i][j] == 1){
if(getNum(i,j,board) < 2) board[i][j] = 3;
else if(getNum(i,j,board) > 3) board[i][j] = 2;
else board[i][j] = 4;
}
else if(board[i][j] == 0){
if(getNum(i,j,board) == 3) board[i][j] = 5;
}
}
} for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(board[i][j] == 4 || board[i][j] == 5) board[i][j] = 1;
else board[i][j] = 0;
}
}
return;
}
public int getNum(int i,int j,int[][] board){
int m = board.length;
int n = board[0].length;
int count = 0;
for(int p = i - 1; p < i + 2; p++){
for(int q = j - 1; q < j + 2; q++){
if(p >= 0 && p < m && q >= 0 && q < n){
if(p == i && q == j) continue;
else{
if(board[p][q] == 1 || board[p][q] == 2 || board[p][q] == 3 || board[p][q] == 4){
count++;
}
}
}
}
}
return count;
}

Subsets

思路:回溯,临界条件:element.length <= nums.length

public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
List<Integer> element = new ArrayList<Integer>();
int k = nums.length;
if(k == 0) return result;
result.add(element); for(int i = 1; i <= k; i++){
getResult(nums,result,element,0,i);
}
return result;
} void getResult(int[] nums,List<List<Integer>> result,List<Integer> element,int start,int k){
if(element.size() == k){
result.add(new ArrayList<Integer>(element));
return;
} for(int i = start;i < nums.length; i++){
element.add(nums[i]);
getResult(nums,result,element,i+1,k);
element.remove(element.size() - 1);
}
} public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
List<Integer> ans = new ArrayList<Integer>();
getResult(nums,res,ans,0);
return res;
} public void getResult(int[] nums,List<List<Integer>> res,List<Integer> ans,int start){
res.add(new ArrayList<Integer>(ans)); for(int i = start; i < nums.length; i++){
ans.add(nums[i]);
getResult(nums,res,ans,i + 1);
ans.remove(ans.size() - 1);
}
}

SubsetsII

思路:和Subsets一样,但是需要去掉重复解决方案,即增加排序和过滤即可

public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
List<Integer> element = new ArrayList<Integer>();
int k = nums.length;
if(k == 0) return result;
result.add(element);
//排序很重要
Arrays.sort(nums); for(int i = 1; i <= k; i++){
getResult(nums,result,element,0,i);
}
return result;
} void getResult(int[] nums,List<List<Integer>> result,List<Integer> element,int start,int k){
if(element.size() == k){
result.add(new ArrayList<Integer>(element));
return;
} for(int i = start;i < nums.length; i++){
//将重复的解决方案过滤掉
if(i != start && nums[i] == nums[i - 1]) continue;
else{
element.add(nums[i]);
getResult(nums,result,element,i+1,k);
element.remove(element.size() - 1);
}
}
}

Word Search

思路:回溯法,构造一个访问数组,访问过标记为true,未访问标记为false,若朝四个方向查找均未找到,则不存在

public boolean exist(char[][] board, String word) {
if(word.length() == 0) return false;
int m = board.length;
if(m == 0) return false;
int n = board[0].length; boolean[][] visited = new boolean[m][n];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
visited[i][j] = false;
}
} for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(board[i][j] == word.charAt(0)){
visited[i][j] = true;
if(word.length() == 1 || search(board,word.substring(1),i,j,visited)) return true;
visited[i][j] = false;
}
}
}
return false;
} public boolean search(char[][] board,String word,int i,int j,boolean[][] visited){
int[][] direction = new int[4][2];
direction[0][0] = direction[1][0] = direction[2][1] = direction[3][1] = 0;
direction[0][1] = direction[2][0] = 1;
direction[1][1] = direction[3][0] = -1;
for(int p = 0; p < 4; p++){
int ii = i + direction[p][0];
int jj = j + direction[p][1];
if(ii >= 0 && ii < board.length && jj >= 0 && jj < board[0].length && !visited[ii][jj] && board[ii][jj] == word.charAt(0)){
visited[ii][jj] = true;
if(word.length() == 1 || search(board,word.substring(1),ii,jj,visited)) return true;
visited[ii][jj] = false;
}
}
return false;
}

Spiral Matrix

思路:记录待处理矩阵左上角和右下角的坐标,每次处理一圈,直到处理完

public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> list = new ArrayList<Integer>();
int row = matrix.length;
if(row == 0) return list;
int col = matrix[0].length; int x = 0;
int y = 0;
while(row >= 1 && col >= 1){
int m = x + row - 1;
int n = y + col - 1;
for(int i = y; i <= n; i++){
list.add(matrix[x][i]);
} for(int i = x + 1; i <= m - 1; i++){
list.add(matrix[i][n]);
} if(row > 1){
for(int i = n; i >= y; i--){
list.add(matrix[m][i]);
}
} if(col > 1){
for(int i = m - 1; i > x; i--){
list.add(matrix[i][y]);
}
}
row -= 2;
col -= 2;
x++;
y++;
}
return list;
}

Maximum Subarray

思路:动态规划,判断前面数的加和是否大于0,sum = (sum < 0) ? nums[i] : (nums[i] + sum);然后每次更新max:max = Math.max(max,sum);

public int maxSubArray(int[] nums) {
if(nums.length == 0) return -1;
if(nums.length == 1) return nums[0];
int max = nums[0];
int sum = nums[0];
for(int i = 1; i < nums.length; i++){
sum = (sum < 0) ? nums[i] : (nums[i] + sum);
max = Math.max(max,sum);
}
return max;
}

Combination Sum

思路:需要计算解决方案中所有数的和,即构造一个参数sum与target比较

public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
List<Integer> ans = new ArrayList<Integer>();
Arrays.sort(candidates);
getResult(res,ans,candidates,0,0,target);
return res;
} public void getResult(List<List<Integer>> res,List<Integer> ans,int[] candidates,int start,int sum,int target){
if(sum == target){
res.add(new ArrayList<Integer>(ans));
return;
}
else if(sum > target) return;
else{
for(int i = start; i < candidates.length; i++){
sum += candidates[i];
ans.add(candidates[i]);
getResult(res,ans,candidates,i,sum,target);
ans.remove(ans.size() - 1);
sum -= candidates[i];
}
}
return;
}

Combination SumII(需要去除重复解决方案)和Combination SumIII(需要判断解决方案数组长度)思路同Combination Sum

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.

思路:本题可以先排序然后遍历得出结果,但是题目要求不能改变原数组,因此不能排序,则采用二分查找的变种算法:我们在区别[1, n]中搜索,首先求出中点mid,然后遍历整个数组,统计所有小于等于mid的数的个数,如果个数小于mid,则说明重复值在[mid+1, n]之间,反之,重复值应在[1, mid-1]之间,然后依次类推,直到搜索完成,此时的low就是我们要求的重复值

public int findDuplicate(int[] nums) {
int m = 0;
int n = nums.length - 1;
while(m <= n){
int mid = m + (n - m) / 2;
int cnt = 0;
for(int i = 0; i < nums.length; i++){
if(nums[i] <= mid) cnt++;
}
if(cnt > mid) n = mid - 1;
else m = mid + 1;
}
return m;
}

Median of Two Sorted Arrays

思路:用快速排序的方法找第k大的数,可是题目要求时间复杂度为O(log(m + n)),于是只能在两个有序数组中使用二分查找

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
return (findKNum(nums1,nums2,(m + n + 1) / 2) + findKNum(nums1,nums2,(m + n + 2) / 2)) / 2.0;
} public int findKNum(int[] nums1,int[] nums2,int k){
int m = nums1.length;
int n = nums2.length;
if(m > n) return findKNum(nums2,nums1,k);
if(m == 0) return nums2[k - 1];
if(k == 1) return Math.min(nums1[0],nums2[0]);
int i = Math.min(m,k / 2);
int j = Math.min(n,k / 2);
if(nums1[i - 1] < nums2[j - 1]) return findKNum(Arrays.copyOfRange(nums1,i,m),nums2,k - i);
else return findKNum(nums1,Arrays.copyOfRange(nums2,j,n),k - j);
} 典型的归并排序
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
int[] res = new int[m + n];
merge(nums1,nums2,res);
if((m + n) % 2 == 1) return (double)res[(m + n - 1) / 2];
else return ((double)res[(m + n - 1) / 2] + res[(m + n) / 2]) / 2;
} public void merge(int[] nums1,int[] nums2,int[] res){
int m = nums1.length;
int n = nums2.length;
int left = 0;
int right = 0;
int i = 0;
while(left < m && right < n){
if(nums1[left] < nums2[right]){
res[i++] = nums1[left++];
}
else{
res[i++] = nums2[right++];
}
}
while(left < m){
res[i++] = nums1[left++];
}
while(right < n){
res[i++] = nums2[right++];
}
}

Trapping Rain Water

思路:找到左边最高水柱和右边最高水柱,两水柱低的那个减去自身水柱就是积攒的面积

public int trap(int[] height) {
int n = height.length;
if(n == 0) return 0;
int[] left = new int[n];
int[] right = new int[n]; //计算坐标i左边最高的水柱
left[0] = height[0];
for(int i = 1; i < n; i++){
left[i] = Math.max(left[i - 1],height[i]);
} //计算坐标i右边最高的水柱
right[n - 1] = height[n - 1];
for(int i = n - 2; i >= 0; i--){
right[i] = Math.max(right[i + 1],height[i]);
} int water = 0;
for(int i = 0; i < n; i++){
water += (Math.min(left[i],right[i]) - height[i]);
}
return water;
}

Jump Game II

思路:动态规划,构造一个dp[n],dp[i]表示到达i所需要的最小跳数

public int jump(int[] nums) {
int n = nums.length;
if(n == 0) return Integer.MAX_VALUE;
//dp[i]表示到达索引i所需要的最小跳数
int[] dp = new int[n];
dp[0] = 0;
for(int i = 1; i < n; i++){
dp[i] = Integer.MAX_VALUE;
}
for(int i = 1; i < n; i++){
for(int j = 0; j < i; j++){
if(j + nums[j] >= i){
int temp = dp[j] + 1;
if(temp < dp[i]){
dp[i] = temp;
break;
}
//由于dp是一个递增序列,因此上面做法可以减少大量的计算
//dp[i] = (dp[i] < dp[j] + i) ? dp[i] : dp[j] + 1;
}
}
}
return dp[n - 1];
}

Longest Consecutive Sequence

思路:遍历查找当前数升序和降序的个数之和,由于同一序列的个数一定相同,则找到的可以直接删掉以减少时间复杂度

public int longestConsecutive(int[] nums) {
HashSet<Integer> set = new HashSet<Integer>();
for(int i = 0; i < nums.length; i++){
set.add(nums[i]);
}
int sum = Integer.MIN_VALUE; for(int i = 0; i < nums.length; i++){
//升序个数
int upCnt = findNum(set,nums[i],true);
//降序个数
int downCnt = findNum(set,nums[i] - 1,false);
sum = Math.max(sum,upCnt + downCnt);
}
return sum;
} public int findNum(HashSet<Integer> set,int num,boolean flag){
int cnt = 0;
while(set.contains(num)){
cnt++;
set.remove(num);
if(flag) num++;
else num--;
}
return cnt;
}

414 排序以后找到第三大的数,考虑数组长度和有重复的数 时间复杂度:O(nlogn)

396 先遍历计算出F(0)和sum,F(n + 1) = F(n) + sum - length * RotateNumber,寻找最大的F

283 两个指针,后指针等于0则往后移,不等于0则覆盖前指针,两指针一起往后移,然后将数组后面补0

217 HashSet 无序不重复

219/169 HashMap key不重复

189 将后面k个元素拿出来放到前面 判断k % length

118/119 递推式:list.get(i).get(j) = list.get(i - 1).get(j - 1) + list.get(i - 1).get(j)

88/75 快速排序

26/27 思路同283

268 排序后判断索引是否与值相等

64 动态规划:grid[i][j] = min(grid[i][j] + grid[i - 1][j],grid[i][j] + grid[i][j - 1])

162 遍历,考虑特殊情况

153/154/81/35/33 遍历

120 动态规划:triangle[i][j] = min(triangle[i][j] + triangle[i - 1][j],triangle[i][j] + triangle[i - 1][j - 1]),注意java中对list某元素赋值只能算完加法运算后然后set,只有数组才能+=

268/41 排序后遍历

74 从右上角开始查找,小就往下,大就往左

73 首先设置两个标志位判断第一行和第一列是否有0,然后遍历整个矩阵将0都映射到第一行和第一列,最后将0的对应行和列都置为0,若第一行和第一列的标志位为true则将其整行或整列都置为0

62 动态规划:res[i][j] = res[i][j - 1] + res[i - 1][j];

55 动态规划:构造一个余力值数组,记录还有多少余力 canWalk[i] = Math.max(canWalk[i - 1],nums[i - 1]) - 1;

167 Two Points

11 Container With Most Water 动态规划:两个指针依次计算面积,长度小的指针往长度高的指针方向移,更新面积

Plus One--->通过%10和/10记录当前数和进位比判断9更有效率

3Sum Closest

Product of Array Except Self

Majority Element II

Maximum Product Subarray

Construct Binary Tree from Preorder and Inorder Traversal

Unique Paths II

Spiral Matrix II

Summary Ranges

Minimum Size Subarray Sum

Search for a Range

Next Permutation(首先从后往前找到第一个降序的索引i,然后找到后面比nums[i]大的最小的数,将它们调换位置,然后将后面的序列翻转)

Rotate Image:将方针顺时针旋转90度:matrix[j][n - i - 1] = copy[i][j];

LeetCode----Array的更多相关文章

  1. [LeetCode] Array Nesting 数组嵌套

    A zero-indexed array A consisting of N different integers is given. The array contains all integers ...

  2. [LeetCode] Array Partition I 数组分割之一

    Given an array of 2n integers, your task is to group these integers into n pairs of integer, say (a1 ...

  3. Leetcode Array 4 Median of Two Sorted Arrays

    做leetcode题目的第二天,我是按照分类来做的,做的第一类是Array类,碰见的第二道题目,也就是今天做的这个,题目难度为hard.题目不难理解,但是要求到了时间复杂度,就需要好好考虑使用一下算法 ...

  4. LeetCode Array Easy 88. Merge Sorted Array

    Description Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted ar ...

  5. LeetCode[Array]----3Sum

    3Sum Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find a ...

  6. leetcode array解题思路

    Array *532. K-diff Pairs in an Array 方案一:暴力搜索, N平方的时间复杂度,空间复杂度N 数组长度为10000,使用O(N平方)的解法担心TLE,不建议使用,尽管 ...

  7. Leetcode Array 16 3Sum Closest

    Given an array S of n integers, find three integers in S such that the sum is closest to a given num ...

  8. Leetcode Array 15 3sum

      思考的方向不对,即使用了多于别人几倍的时间,也不一定能够达到终点. 我的错误的想法(可以跳过):在leetcode上面做的第四道题,走路一个很大的弯路,收到之前做过的 Container With ...

  9. Leetcode Array 1 twoSum

    Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...

  10. LeetCode Array Easy 485. Max Consecutive Ones

    Description Given a binary array, find the maximum number of consecutive 1s in this array. Example 1 ...

随机推荐

  1. 北大poj-2688

    Cleaning Robot Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4395   Accepted: 1763 De ...

  2. sudo: /etc/sudoers is world writable

    错误信息: sudo: /etc/sudoers is world writable sudo: no valid sudoers sources found, quitting 解决办法: 修复磁盘 ...

  3. nexus7 二代 升级 android L

    折腾了半天 ,最后发现其实很简单... 1.装好windows下gdb和bootloader的驱动,注意打开usb debug,另外进入bootloader是开机按电源键和音量减小键,至于要解锁这个想 ...

  4. hession

    Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能. 相比WebService,Hessian更简单.快捷.采用的是二进制RPC协议,因为采用的是二进制协 ...

  5. 如何开发、调试Hybrid项目-- 入门篇

    前言 随着移动浪潮的兴起,各种APP层出不穷,极速的业务扩展提升了团队对开发效率的要求,这个时候使用IOS&Andriod开发一个APP似乎成本有点过高了,而H5的低成本.高效率.跨平台等特性 ...

  6. 第六周——分析Linux内核创建一个新进程的过程

    "万子恵 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 &q ...

  7. (转)如何处理iOS中照片的方向

    如何处理iOS中照片的方向 31 May 2015 • 7 min. read • Comments 使用过iPhone或者iPad的朋友在拍照时不知是否遇到过这样的问题,将设备中的照片导出到Wind ...

  8. c#读写文件

    1.添加命名空间 System.IO; System.Text; 2.文件的读取 (1).使用FileStream类进行文件的读取,并将它转换成char数组,然后输出. byte[] byData = ...

  9. Discuz 7.0版块横排显示版块图标和版块简介的方法

    Discuz 7.0版块横排显示版块图标和版块简介的方法 最近很多朋友咨询Discuz论坛设置论坛版块横排后,如何设置显示版块图标和简介的问题. 一.显示板块图标 找到templates\defaul ...

  10. Unity3d游戏场景优化杂谈(3)

    LOD(Level-of-detail)是最常用的游戏优化技术 .如果你的程序可以定制开发应用LOD的模块,当然 是很美好的事情.不过如果没有也没关系,大家可以使用UniLOD这个第三方的LOD插件. ...