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 ...
随机推荐
- cocos2d-x 3.0 事件分发机制
在cocos2d-x 3.0中一共有五个事件监听器: 触摸事件(EventListenerTouch) 键盘响应事件 (EventListenerKeyboard) 加速器记录事件(EventList ...
- 用springMVC构建restful程序,接收以及返回json数据格式
主要参考文章:http://kingxss.iteye.com/blog/1487745和http://blog.csdn.net/greensurfer/article/details/192962 ...
- initcall调用顺序
在解释initcall调用顺序, 先要理一下编译链接的知识. 每个.o文件都有自己的代码段, 数据段(存放初始化的全局变量), bss段(即未初始化的数据段) 在ld链接器将各.o文件的代码段和数据段 ...
- 第三次作业——for 语句及分支结构else-if
1.本次学习到的知识点: (1)else-if的一般形式:if(表达式1)语句1:else if(表达式2)语句2:........else if(表达式n-1)语句n-1:else语句n: (2)遇 ...
- mac下安装和配置mysql5.7.9
我安装的是5.7.9版本的sql 一开始在网上看到的都是其他版本的安装,弄得自己卸载了好几次 mysql就只有一个dmg主文件,安装这一个就好了. 5.7以后安装的mysql不再使用旧版的默认密码:r ...
- 操作系统学习笔记(五)--CPU调度
由于第四章线程的介绍没有上传视频,故之后看书来补. 最近开始学习操作系统原理这门课程,特将学习笔记整理成技术博客的形式发表,希望能给大家的操作系统学习带来帮助.同时盼望大家能对文章评论,大家一起多多交 ...
- 2014嘉杰信息杯ACM/ICPC湖南程序设计邀请赛暨第六届湘潭市程序设计竞赛
比赛链接: http://202.197.224.59/OnlineJudge2/index.php/Contest/problems/contest_id/36 题目来源: 2014嘉杰信息杯ACM ...
- Android中proc/meminfo的详解(原)
今天在写到获取手机可用内存空间的总大小的时候,通过下面的方法去获取的时候,发现该方法最低支持的版本是16,这显然是不可取的. public static long getTotalSpace(Cont ...
- 在windows下配置wnmp
1.下载mysql 2.下载php 3.下载nginx 4.创建文件夹wnmp 把php,nginx,mysql放到wnmp目录下,另外新建www目录, 用于存放web文件 配置nginx,如下(ng ...
- 深入剖析ConcurrentHashMap(2)
转载自并发编程网 – ifeve.com本文链接地址: 深入剖析ConcurrentHashMap(2) 经过之前的铺垫,现在可以进入正题了.我们关注的操作有:get,put,remove 这3个操作 ...