提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
445
376
53
122、买卖股票的最佳时机
和摆动序列很像,加入波峰波谷,注意特定条件就可
第一遍忘了加length<2的情况
class Solution {
public int maxProfit(int[] prices) {
int count =0;
if(prices.length<2){
return count;
}
List<Integer> nums = new ArrayList<>();
if(prices[1]-prices[0]>=0){
nums.add(prices[0]);
}
for(int i=2; i<prices.length;i++){
if(nums.size()%2==1){
if(prices[i]-prices[i-1]<0){
nums.add(prices[i-1]);
}
}
if(nums.size()%2==0){
if(prices[i]-prices[i-1]>0){
nums.add(prices[i-1]);
}
}
}
if(nums.size()%2==1){
nums.add(prices[prices.length-1]);
}
for(int j=1; j<nums.size();j=j+2){
count+=nums.get(j)-nums.get(j-1);
}
return count;
}
}
但其实答案的思路更简单,只需要把正利润都加起来即可
// 贪心思路
class Solution {
public int maxProfit(int[] prices) {
int result = 0;
for (int i = 1; i < prices.length; i++) {
result += Math.max(prices[i] - prices[i - 1], 0);
}
return result;
}
}
45.
走上一步的过程中计算下一步最远走到哪,这一题只需要考虑范围就可以
碰到的问题: 终止条件应该放前面,不然在nums.length-1这一步正好是currDistance会遇到问题
class Solution {
public int jump(int[] nums) {
int currDistance=0;
int count =0;
int maxDistance=0;
if(nums.length==1 || nums.length==0){
return 0;
}
for(int i=0;i<nums.length;i++){
maxDistance=Math.max(maxDistance,i+nums[i]);
if(maxDistance>=nums.length-1){
count++;
break;
}
if(i==currDistance){
count++;
currDistance=maxDistance;
}
}
return count;
}
}
1005. 翻转k次,求数列最大和
先排序,依次把绝对值最大的负数变为整数
如果k不够用(没有完全翻转负数)直接返回sum
如果k够用则分类讨论k剩下奇数个还是偶数个,
如果是偶数个则没有影响; 如果是奇数则重新排序,将最小值变为负数求和:
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
Arrays.sort(nums);
int sum=0;
for(int i=0; i<nums.length;i++){
if(k>0 && nums[i]<0){
nums[i]=-nums[i];
k--;
}
sum+=nums[i];
}
Arrays.sort(nums);
return sum-(k%2==0? 0:2*nums[0]);
}
}
134. 加油站
注意如果一条路径上(从x出发,到y,但是无法通过y到达y的下一站),那么从此路径上的任何一站出发都无法到达y的下一站
因此我们进行减枝操作,i=i+count+1, 其中count为此站点可以到达的站数,通过此操作我们直接重设起点为无法到达的站点
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
int i = 0;
while (i < n) {
int sumOfGas = 0, sumOfCost = 0;
int cnt = 0;
while (cnt < n) {
int j = (i + cnt) % n;
sumOfGas += gas[j];
sumOfCost += cost[j];
if (sumOfCost > sumOfGas) {
break;
}
cnt++;
}
if (cnt == n) {
return i;
} else {
i =i + cnt + 1;
}
}
return -1;
}
}
遇到的问题:
注意当前站点j的递增,通过i与到达站点作和取余完成,其中count自增(count++)
135. 分发糖果
不要同时考虑两边;
第一遍前序遍历,考虑右边是否比左边ratings高,如果高就在前面的糖果数量+1,不高直接给1;
第二遍后序遍历,考虑左侧是否比右侧ratings高,如果高,就比较左边现有糖果和右侧现有数量+1谁大,取大的值;
class Solution {
public int candy(int[] ratings) {
int length = ratings.length;
int[] candyVec = new int[length];
candyVec[0]=1;
int sum=0;
for(int i =0; i<length-1;i++){
candyVec[i+1]=(ratings[i+1]>ratings[i])? candyVec[i]+1:1;
}
for(int i=length-2;i>=0;i--){
if(ratings[i]>ratings[i+1]){
candyVec[i]=Math.max(candyVec[i],candyVec[i+1]+1);
}
}
for(int num:candyVec){
sum+=num;
}
return sum;
}
}
860. 柠檬水找零
注意加入判断逻辑,5块钱多的时候先用5块钱找20的零钱
class Solution {
public boolean lemonadeChange(int[] bills) {
int[] res = new int[3];
for(int num:bills){
if(num==5){
res[0]++;
}else if(num==10){
res[0]--;
res[1]++;
if(res[0]<0){
return false;
}
}else{
if(res[0]>res[1] && res[0]>=3){
res[0]=res[0]-3;
}else{
res[0]--;
res[1]--;
res[2]++;
}
if(res[0]<0||res[1]<0){
return false;
}
}
}
return true;
}
}
406.根据身高重建队列
注意Arrays.sort()的实现方法;
先排序空位多(person[1])对排序空位少的没有影响
class Solution {
public int[][] reconstructQueue(int[][] people) {
Arrays.sort(people, new Comparator<int[]>(){
public int compare(int []person1, int[] person2){
if(person1[0]!=person2[0]){
return person1[0]-person2[0];
}else{
return person2[1]-person1[1];
}
}
});
int n=people.length;
int[][] ans= new int[n][];
for(int[] person: people){
int space = person[1];
for(int i=0; i<n;i++){
if(ans[i]==null){
if(space==0){
ans[i]=person;
break;
}
space--;
}
}
}
return ans;
}
}
区间问题
452. 用最少数量的箭引爆气球
注意更新右边界
class Solution {
public int findMinArrowShots(int[][] points) {
// 根据气球直径的开始坐标从小到大排序
// 使用Integer内置比较方法,不会溢出
Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));
int count = 1; // points 不为空至少需要一支箭
for (int i = 1; i < points.length; i++) {
if (points[i][0] > points[i - 1][1]) { // 气球i和气球i-1不挨着,注意这里不是>=
count++; // 需要一支箭
} else { // 气球i和气球i-1挨着
points[i][1] = Math.min(points[i][1], points[i - 1][1]); // 更新重叠气球最小右边界
}
}
return count;
}
}
435. 无重叠区间
与射箭做法类似
注意要用Math.min获取最小有边界
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals,(a,b)->{
return Integer.compare(a[0],b[0]);
});
int count=1;
for(int i=1;i<intervals.length;i++){
if(intervals[i][0]<intervals[i-1][1]){
intervals[i][1]=Math.min(intervals[i][1], intervals[i-1][1]);
}else{
count++;
}
}
return intervals.length-count;
}
}
763. 划分字母区间
引入idx为当前字母出现的最远位置,从下一个位置开始,到这个字母的最远位置结束;
如果出现新的最远位置超过目前的最远位置则更新最远位置
class Solution {
public List<Integer> partitionLabels(String S) {
List<Integer> list = new LinkedList<>();
int[] edge = new int[26];
char[] chars = S.toCharArray();
for (int i = 0; i < chars.length; i++) {
edge[chars[i] - 'a'] = i;
}
int idx = 0;
int last = -1;
for (int i = 0; i < chars.length; i++) {
idx = Math.max(idx,edge[chars[i] - 'a']);
if (i == idx) {
list.add(i - last);
last = i;
}
}
return list;
}
}
56. 合并区间
class Solution {
public int[][] merge(int[][] intervals) {
if(intervals.length==0){
return new int[1][2];//[0][2]还是[1][2]
}
Arrays.sort(intervals,new Comparator<int[]>(){
public int compare(int[] interval1, int[] interval2){
return interval1[0]-interval2[0];
}
});
List<int[]> merged = new ArrayList<int[]>();
for(int i=0;i<intervals.length;i++){
int L=intervals[i][0];
int R=intervals[i][1];
if(merged.size()==0 || L>merged.get(merged.size()-1)[1]){
merged.add(new int[]{L,R});
}else{
merged.get(merged.size()-1)[1]=Math.max(merged.get(merged.size()-1)[1],R);
}
}
return merged.toArray(new int[merged.size()][]);//二维数组也可以用toArray转换
}
}