https://leetcode-cn.com/contest/weekly-contest-288/
/*
* 1、每个数和后面数判断是否同为奇同为偶,可以直接两个数相加看是否为奇数,
* 因为奇偶性相同的两个数相加一定是偶数,奇偶数不同的两个数相加一定是奇数!
* 字符直接对应着ascii码,不必再减去'0'转成数字;
* 2、每次往后遍历只需要找到最大的数,和最大的数做一次交换即可!
*
* 执行用时:1 ms, 在所有 Java 提交中击败了93.38%的用户
* 内存消耗:38.5 MB, 在所有 Java 提交中击败了46.16%的用户
*/
public int largestInteger(int num) {
//首先吧num转换成String再转换成char型数组
String s = String.valueOf(num);
char[] chs = s.toCharArray();
for(int i=0; i<s.length(); i++){
int maxIdx = i;//最大的数的index
for(int j=s.length()-1; j>=i; j--){
//奇偶性相同的两个数的差的取2模为0
if(((chs[i] - '0' + chs[j] - '0') % 2 == 0)){
if(chs[j] > chs[maxIdx]){
maxIdx = j;
}
}
}
if(maxIdx != i){
char temp = chs[i];
chs[i] = chs[maxIdx];
chs[maxIdx] = temp;
}
}
return Integer.parseInt(new String(chs));
}
比赛时代码:
/*
* 两对双指针,一对排奇,一对排偶
*/
public int largestInteger1(int num) {
int[] nums = change(num);
int len = nums.length;
int oddl = 0;
int oddr = len-1;
int evenl = 0;
int evenr = len-1;
while(oddl < oddr){
if(nums[oddl]%2 == 1 && nums[oddr]%2 == 1){//两个指针都找到了奇数
}
}
return 1;
}
//将int转换为int[]
public int[] change(int num){
int temp = num;//输入的整数
int wei = 0;//几位数
ArrayList<Integer> list = new ArrayList<Integer>();
//算出位数
while(temp!=0){
temp = temp/10;
wei++;
}
//创建一个和整数位数相同大小的数组
int[] element = new int[wei];
int tmp = num;
for(int i = wei;i>0;i--){
//从高位到低位依次取数字
int m1 = (new Double(Math.pow(10,i-1))).intValue();
tmp = (num/m1)%10;
element[wei-i] = tmp;
}
return element;
}
参考计算器
https://leetcode-cn.com/problems/minimize-result-by-adding-parentheses-to-expression/
int addIndex = expression.indexOf('+');
int len = expression.length();
int min = Integer.MAX_VALUE;
int[] pair = new int[2];
// 以addIndex为分界线两边进行分割
for (int i = 0; i < addIndex; i++) {//加号前的num
for (int j = addIndex + 2; j <= len; j++) {//加号后的num
String s1 = expression.substring(0, i);
int num1 = "".equals(s1) ? 1 : Integer.parseInt(s1);
String s2 = expression.substring(i, addIndex);
int num2 = Integer.parseInt(s2);
String s3 = expression.substring(addIndex + 1, j);
int num3 = Integer.parseInt(s3);
String s4 = expression.substring(j, len);
int num4 = "".equals(s4) ? 1 : Integer.parseInt(s4);
int num = num1 * (num2 + num3) * num4;
if (num < min) {
pair = new int[]{i, j};
min = num;
}
}
}
StringBuilder sb = new StringBuilder(expression);
sb.insert(pair[0], '(');
sb.insert(pair[1] + 1, ')');
return sb.toString();
public class Main {
public static void main(String args[]) {
String string = "aaa456ac";
//查找指定字符是在字符串中的下标。在则返回所在字符串下标;不在则返回-1.
System.out.println(string.indexOf("b")); // indexOf(String str); 返回结果:-1,"b"不存在
// 从第四个字符位置开始往后继续查找,包含当前位置
System.out.println(string.indexOf("a",3));//indexOf(String str, int fromIndex); 返回结果:6
//(与之前的差别:上面的参数是 String 类型,下面的参数是 int 类型)参考数据:a-97,b-98,c-99
// 从头开始查找是否存在指定的字符
System.out.println(string.indexOf(99));//indexOf(int ch);返回结果:7
System.out.println(string.indexOf('c'));//indexOf(int ch);返回结果:7
//从fromIndex查找ch,这个是字符型变量,不是字符串。字符a对应的数字就是97。
System.out.println(string.indexOf(97,3));//indexOf(int ch, int fromIndex); 返回结果:6
System.out.println(string.indexOf('a',3));//indexOf(int ch, int fromIndex); 返回结果:6
}
}
public class RunoobTest {
public static void main(String args[]) {
String Str = new String("This is text");
System.out.print("返回值 :" );
System.out.println(Str.substring(4) );
System.out.print("返回值 :" );
System.out.println(Str.substring(4, 10) );
}
}
返回值 : is text
返回值 : is te
https://leetcode-cn.com/problems/maximum-product-after-k-increments/
贪心+优先队列
/*
* 1.把所有起始数字放进一个最小堆优先队列。
* 2.进行k次操作,每次取出队列中最小值,并对其进行加一操作,再放回队列。
* 3.最后把队列中所有数字相乘就是答案了(注意步步取余防止溢出,证明(a+b)%c = (a%c+b%c)%c)。
*
* 执行用时:196 ms, 在所有 Java 提交中击败了81.96%的用户
* 内存消耗:52.4 MB, 在所有 Java 提交中击败了32.28%的用户
*/
public int maximumProduct(int[] nums, int k) {
PriorityQueue<Integer> pq = new PriorityQueue<>();
for (int num : nums){
pq.offer(num);
}
for (int i = 0; i < k; i++){
int num = pq.poll();
num += 1;
pq.offer(num);
}
long ans = 1;
long MOD = 1000000007;
for (int num : pq){
ans = (num * ans) % MOD;
}
return (int)ans;
}
比赛时代码:
/*
* 8 / 73 个通过测试用例
*/
public int maximumProduct1(int[] nums, int k) {
int len = nums.length;
long MOD = 1000000007;
int[][] dp = new int[k][len];
int addindex = 0;
int tosum = 0;//当前行最大乘积
for(int j=0; j<k; j++){
addindex = 0;
tosum = 0;//当前行最大乘积
for(int i=0; i<nums.length; i++){
nums[i] += 1;
dp[j][i] = cheng(nums, MOD);
if(dp[j][i] > tosum) {
tosum = dp[j][i];
addindex = i;
}
nums[i] -= 1;
}
nums[addindex]++;
show1(nums);
}
return (int) (tosum%MOD);
}
public int cheng(int[] nums, long MOD){
int res = nums[0];
for(int i=1; i<nums.length; i++) {
//System.out.print("当前res为:" + res + ",当前");
res = (int) ((res*nums[i])%MOD);
}
return res;
}
https://leetcode-cn.com/problems/maximum-total-beauty-of-the-gardens/
//核心思路:
//1.如果要填充完善花园,一定是优先填种花数最多的花园,因此容易想到排序数组,然后逆序遍历进行填充
//2.如果不填充为完善花园,那就要使得所有不完善花园种花数的最小值最大
//3.But,填还是不填我们并不知道,需要根据full和partial的值确定,不过这个分类讨论就太细了没法做。因此!填和不填两种情况的美丽值我们都算出来,取最大值就行了!
//4.根据上述三点,我们可以逆序遍历数组,对于每个花园,我们分别计算不填充为完善花园(当前花园和之前花园都不填充)的美丽值,以及当前花园填充为完善花园,然后继续循环,在下一个花园上走相同逻辑!
//详细步骤见代码注释
//注意,newFlowers表示最大可种新花数目,即种的新花数目也可以小于newFlowers,甚至可以不种新花
class Solution {
public long maximumBeauty(int[] flowers, long newFlowers, int target, int full, int partial) {
//升序
Arrays.sort(flowers);
int n = flowers.length;
//种花最少的花园已经达到了target,可直接返回结果
if (flowers[0] >= target) return (long)n * full;
//前缀和,sum[i]表示前i个花园累积已经种花的数量,这个仅仅用于后续的一步计算,不是重点
long[] sum = new long[n];
sum[0] = flowers[0];
for (int i = 1; i < n; i++){
sum[i] = sum[i - 1] + flowers[i];
}
//保存最终结果
long ans = 0;
//逆序遍历,优先把种花数多的花园,填满至target
for (int i = n - 1; i >= 0; i--) {
//当前花园种花数已经>=target,不处理
if (flowers[i] >= target) continue;
//当前花园种花数 < target时,此时有两种选择:
//1.当前花园以及前面花园都不填充为完善花园,使得当前花园以及前面花园种花数的最小值最大!(例如partial远大于full的情况,此时把新种花指标用在增大不完善花园的最小值上对结果增益更大,但要牢牢记住这些花园都不能填充为完善花园)
//2.当前花园填充成完善花园,再继续循环处理前面花园的情况(例如full比较大的情况,此时把新种花指标用在凑完善花园上对结果增益更大)
//针对1,要使得当前花园以及前面花园都不能填充为完善花园,则这些花园的种花数范围必定在[flowers[0], target - 1]内,flowers[0]是种花数最小的花园,题目也说了已经种了的花不能移走,因此左边界是flowers[0]
//那么新花种完以后,这些花园的种花数最小值必定在这个范围内,如此转化为:在一个递增区间内,找最后一个满足xxx条件的数minVal,典型二分查找问题。(因为要尽可能使这个最小值最大嘛,所以要找最后一个满足条件的!!)
//而这个xxx条件就是指,能否用newFlowers把当前花园以及前面花园种花数小于minVal的全都填满到minVal
long l = flowers[0], r = target - 1;
while (l < r) {
long mid = (r - l + 1) / 2 + l;
if (check(flowers, sum, newFlowers, mid, i)) {
l = mid;
} else {
r = mid - 1;
}
}
//这里计算了选择1情况下的美丽值,并更新全局最大美丽值
ans = Math.max(ans, (n - i - 1) * (long)full + l * partial);
//继续走选择2,继续循环
newFlowers -= target - flowers[i];
//注意,如果newFlowers不足以把当前花园填充为美丽花园,那说明只能走选择1了,而且后续的花园都不能填充了
//直接结束,返回ans!
if (newFlowers < 0) return ans;
}
//循环能走出来,说明全部花园都可以填充为完善花园
//处理边界情况,也就是全部花园都填成完善花园的情况,上面循环中最后这次少计算了
if (newFlowers >= 0) return Math.max(ans, (long)full * n);
return ans;
}
//能否用newFlowers把flowers[0, idx]中小于num的花园都填满到minVal
public boolean check(int[] flowers, long[] sum, long newFlowers, long minVal, int idx) {
int l = 0, r = idx;
//既然要填满所有小于minVal的元素,那就要找最后一个小于minVal的元素,继续二分!
while (l < r) {
int mid = l + r + 1 >> 1;
if (flowers[mid] < minVal) {
l = mid;
} else {
r = mid - 1;
}
}
//此时flowers[0,l]都是小于minVal的,计算一下填满它们需要的花数量
long diff = minVal * (l + 1) - sum[l];
//如果newFlowers够填,返回true;不够,返回false
return newFlowers >= diff;
}
}