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. 好文mark

    用oracle的dblink连接mysql. http://f.dataguru.cn/thread-267150-1-1.html hadoop的机架感知: 本地化策略,以及备份都要知道哪个节点在哪 ...

  2. grep查询文本:问一个简单shell问题,将grep的输出赋值给一个变量

    问一个简单shell问题,将grep的输出赋值给一个变量 用grep命令得到的输出赋值给一个变量不成功. grep命令如下: 代码: $ grep -c '^abc' file.txt 输出为22,表 ...

  3. HTML 30分钟入门教程

    作者:deerchao 转载请注明来源 本文目标 30分钟内让你明白HTML是什么,并对它有一些基本的了解.一旦入门后,你可以从网上找到更多更详细的资料来继续学习. 什么是HTML HTML是英文Hy ...

  4. 三种renderman规范引擎的dice对比

    次表面做的有些烦躁,既然如此,索性先记一下前一阵比较的PIXIE.3delight.prman的dice方式. 研究过reyes的人都知道dice,简而言之,就是为了生成高质量高精度的图片(电影CG) ...

  5. Xcode下的批量编辑

    说明:目前为止我找到三种查找与替换功能,如果有更多的方式,请在下面留言 第一种:我们常用的查找以及查找与替换功能 在Windows下,使用Ctrl+f 快捷键查找.用Ctrl+h来进行查找与替换功能. ...

  6. 驱动实现led,pwm和中断基础知识

    2015.4.8星期三 晴天 今天老师讲的内容是内核编写led和pwm驱动,实现花样灯和放歌的功能.理解应用和驱动的对接,最后自己实现了在放歌的时候根据歌曲的节奏亮灭一个小灯,应为两个独立的驱动都已经 ...

  7. Struts 2 Spring Hibernate三大框架的执行流程以及原理

    Struts2框架 一.简介 Struts2是一个相当强大的Java Web开源框架,是一个基于POJO的Action的MVC Web框架.它基于当年的WebWork和XWork框架,继承其优点,同时 ...

  8. A Simple Problem with Integers_树状数组

    Problem Description Let A1, A2, ... , AN be N elements. You need to deal with two kinds of operation ...

  9. Javascript之Prototype

    1.原型设计模式 在.Net中可以使用clone()来实现原型法 原型法的主要思想是,现在有1个类A,我想要创建一个类B,这个类是以A为原型的,并且能进行扩展.我们称B的原型为A. 2.javascr ...

  10. 使用RelativeLayout控制WebView以及Bottom按钮的位置

    使用RelativeLayout控制WebView以及Bottom按钮的位置 (地址) 在Design View中加入控件RelativeLayout, WebView, LinearLayout(H ...