LeetCode----Array
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的更多相关文章
- [LeetCode] Array Nesting 数组嵌套
A zero-indexed array A consisting of N different integers is given. The array contains all integers ...
- [LeetCode] Array Partition I 数组分割之一
Given an array of 2n integers, your task is to group these integers into n pairs of integer, say (a1 ...
- Leetcode Array 4 Median of Two Sorted Arrays
做leetcode题目的第二天,我是按照分类来做的,做的第一类是Array类,碰见的第二道题目,也就是今天做的这个,题目难度为hard.题目不难理解,但是要求到了时间复杂度,就需要好好考虑使用一下算法 ...
- LeetCode Array Easy 88. Merge Sorted Array
Description Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted ar ...
- 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 ...
- leetcode array解题思路
Array *532. K-diff Pairs in an Array 方案一:暴力搜索, N平方的时间复杂度,空间复杂度N 数组长度为10000,使用O(N平方)的解法担心TLE,不建议使用,尽管 ...
- 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 ...
- Leetcode Array 15 3sum
思考的方向不对,即使用了多于别人几倍的时间,也不一定能够达到终点. 我的错误的想法(可以跳过):在leetcode上面做的第四道题,走路一个很大的弯路,收到之前做过的 Container With ...
- Leetcode Array 1 twoSum
Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...
- LeetCode Array Easy 485. Max Consecutive Ones
Description Given a binary array, find the maximum number of consecutive 1s in this array. Example 1 ...
随机推荐
- C语言实现栈
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef struct stack_t ...
- Appium学习笔记(一)--安装与配置
移动自动化测试常用工具有两个:Appium和Robotium.正好最近自己开始负责客户端的工作,初来乍到需要熟悉下环境,正好学习新的东西. 移动自动化相对web来说,原理与操作过程是一样的,通过自动化 ...
- U盘又中毒了,隐藏文件如何显示
在 开始--运行 中输入 cmd ,再输入,attrib -H -S D:\123 /s /d 后回车,你就发现问题解决了.注意命令之间的空格,D:\代表盘符,就是你的移动硬盘的盘符,如果你的盘符是E ...
- python-tab还是space?
今天把windows下的python代码传到服务器上,结果莫名其妙的报了一堆indent的错误 网上建议说用: python -m tabnanny filename.py 查一下 然后就用space ...
- iOS信号量的使用
Core Audio render thread and thread signalling up vote2down votefavorite Does iOS have any kind of ...
- Linux手动释放缓存的方法
Linux释放内存的命令:syncecho 1 > /proc/sys/vm/drop_caches drop_caches的值可以是0-3之间的数字,代表不同的含义:0:不释放(系统默认值)1 ...
- Linux学习之路—磁盘分区
1.各硬件设备在Linux中的文件名 在Linux系统中,每个设备都被当做一个文件来对待,同时在Linux系统中,几乎所有的硬件设备文件都在/dev这个目录中. 设备 设备在Linux内的文件名 ID ...
- Python::re 模块 -- 在Python中使用正则表达式
前言 这篇文章,并不是对正则表达式的介绍,而是对Python中如何结合re模块使用正则表达式的介绍.文章的侧重点是如何使用re模块在Python语言中使用正则表达式,对于Python表达式的语法和详细 ...
- css中font-size的单位总结:px、em、pt
px:基于像素的单位.像素是一种有用的单位,因为在任何媒体上都可以保证一个像素的差别确实是可见的.em :一般用来测量长度的通用单位(例如元素周转的页边空白和填充),当用于指定字体大小时,em单位是指 ...
- Fiddler2 主菜单
Fiddler2 主菜单 六个主菜单分别是: 文件(File) Capture Traffic ——启用捕获功能,快捷键 F12 此功能的开启/关闭状态,程序安装后默认是开启的.可以在 Fiddler ...