Arrays分类算法-Min Rewards(待完成)

题目要求

在这里插入图片描述
** 解法一:**
建立空数组存储结果,全部初始化为1。 从头开始遍历数组,如果出现比之前一个小的数,则反向继续遍历,将原来的分数进行更新(更新过程中需要比较新分数和原来久分数的大小,取最大值)。如果出现比之前的数组大,则原有的数+1。继续下一个数的判断。
Time: O(n^2) Space: O(n)
代码:

import java.util.*;

class Program {
  public static int minRewards(int[] scores) {
    // Write your code here.
		int[] res = new int[scores.length];
		res[0] = 1;
		// Arrays.fill(res, 1);
		for (int i = 1; i < scores.length; i++) {
			int j = i - 1;
			if (scores[i] < scores[j]) {
				res[i] = 1;
				while (j >= 0 && scores[j] > scores[j + 1]) {
					res[j] = Math.max(res[j + 1] + 1, res[j]);
					j--;
				}
			} else {
				res[i] = res[i - 1] + 1;
			}
		}
		return sum(res);
  }
	
	public static int sum (int[] array) {
		int sum = 0;
		for (int num : array) {
			sum += num;
		}
		return sum;
	}
}

解法二:
只通过一次遍历数组就得出结果。首先找到数组的localMin的索引并存储。依次处理每个localMin的点,分别向左和向右进行更改分数(更新过程中需要比较新分数和原来久分数的大小,取最大值)。
Corner case:要注意最左边和最右边的极端的点,只有一侧递增。容易越界。
Time: O(n) Space: O(n)
代码:

import java.util.*;

class Program {
  public static int minRewards(int[] scores) {
    // Write your code here.
		if (scores.length == 1) return 1;
		int[] res = new int[scores.length];
		Arrays.fill(res, 1);
		List<Integer> localMinIdxs = getLocalMinIdxs(scores);
		for (Integer localMinIdx : localMinIdxs) {
			calculateRewards(scores, localMinIdx, res);
		}
		return sum(res);
  }
	public static List<Integer> getLocalMinIdxs(int[] array) {
		List<Integer> localMinIdxs = new ArrayList<>();
		for (int i = 0; i < array.length; i++) {
			if (i == 0 && array[i] < array[i + 1]) localMinIdxs.add(0);
			if (i == array.length - 1 && array[i] < array[i - 1])	localMinIdxs.add(i);
			if (i == 0 || i == array.length - 1) continue;
			if (array[i] < array[i - 1] && array[i] < array[i + 1]) {
				localMinIdxs.add(i);
			}
		}
		return localMinIdxs;
	}
	
	public static void calculateRewards(int[] scores, Integer localMinIdx, int[] res) {
		int left = localMinIdx - 1;
		while (left >= 0 && scores[left] > scores[left + 1]) {
			res[left] = Math.max(res[left], res[left + 1] + 1);
			left--;
		}
		
		int right = localMinIdx + 1;
		while (right < scores.length && scores[right] > scores[right - 1]) {
			res[right] = Math.max(res[right], res[right - 1] + 1);
			right++;
		}
	}
	
	public static int sum (int[] array) {
		int sum = 0;
		for (int num : array) {
			sum += num;
		}
		return sum;
	}
}

解法三:
总体来讲和第二种解法思路一样,只不过不需要记录localMin的索引,从前和从后分别遍历一遍,只找后一个数比自己大的去更新分数(更新过程中需要比较新分数和原来久分数的大小,取最大值)。这个方法模拟了找localMin的处理方法。
Time: O(n) Space: O(n)
代码:

import java.util.*;

class Program {
  public static int minRewards(int[] scores) {
    // Write your code here.
		int[] res = new int[scores.length];
		Arrays.fill(res, 1);
		for (int i = 1; i < scores.length; i++) {
			if (scores[i] > scores[i - 1]) {
				res[i] = Math.max(res[i], res[i - 1] + 1);
			}
		}
		for (int i = scores.length - 2; i >= 0; i--) {
			if (scores[i] > scores[i + 1]) {
				res[i] = Math.max(res[i], res[i + 1] + 1);
			}
		}
		return sum(res);
  }
	
	public static int sum (int[] array) {
		int sum = 0;
		for (int num : array) {
			sum += num;
		}
		return sum;
	}
}

解法四:
直接把第一个reward设置为0,从头扫描一遍,如遇递增则a[i] = a[i-1] + 1,否则为a[i] = a[i-1] - 1,期间记录a[i]的最小值,单独处理头递增/尾递减,最后统一处理负数。
Time: O(n) Space: O(n)
代码:

import java.util.*;

class Program {
  public static int minRewards(int[] scores) {
    // Write your code here.
    	int len = scores.length;
		int[] res = new int[len];
		int sum = 0;
		int minVal = 1;
		for (int i = 1; i < len; i++) {
			if (scores[i] > scores[i - 1]) {
				res[i] = res[i - 1] + 1;
			}
			else res[i] = res[i - 1] - 1;
			sum += res[i];
			minVal = Math.min(res[i], minVal);
		}
		
		if (scores[0] < scores[1]) {
			sum = sum - res[0] + minVal;
		}
			
		if (scores[len - 1] < scores[len - 2]) {
			sum = sum - res[len - 1] + minVal;
		}
		
		return sum + (Math.abs(minVal) + 1) * len;
  }
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值