新的解题思路
一、三数之和的多种可能
给定一个整数数组 arr
,以及一个整数 target
作为目标值,返回满足 i < j < k
且 arr[i] + arr[j] + arr[k] == target
的元组 i, j, k
的数量。
由于结果会非常大,请返回 109 + 7
的模。
输入:arr = [1,1,2,2,3,3,4,4,5,5], target = 8 输出:20 解释: 按值枚举(arr[i], arr[j], arr[k]): (1, 2, 5) 出现 8 次; (1, 3, 4) 出现 8 次; (2, 2, 4) 出现 2 次; (2, 3, 3) 出现 2 次。
思路:
使用一个for循环,固定起点。相向双指针比较复杂,因为会有相同的数的情况被忽略掉。
所以使用单指针+哈希表判断。for循环+单指针已经固定了两个数。只需要判断map中是否存在target-a-b.如果存在,res+=map.get(target-a-b); 然后把单指针指向的数字放进去。
代码:
class Solution {
public int threeSumMulti(int[] arr, int target) {
int res=0;
for(int i=0;i<arr.length-2;i++){
int num=arr[i];
HashMap<Integer,Integer> map=new HashMap<>();
int left=i+1;
while(left<arr.length){
int other=target-num-arr[left];
res=(res+map.getOrDefault(other,0))%(int)(1e9+7);
map.put(arr[left],map.getOrDefault(arr[left],0)+1);
left++;
}
}
return res;
}
}
二、令牌放置
题意:
给定一个数组tokens[],里面装了下标为i的令牌的值,并且给定一个power,表示你的能量;
如果你的power>token[i]的,你可以利用power换取一个积分;
你也可以使用积分,去换取能量;你的目标是通过有策略地使用这些令牌以 最大化 总 分数
在使用 任意 数量的令牌后,返回我们可以得到的最大 分数 。
思路:
贪心策略:如果我们使用tokens[i]值小的令牌换取积分。然后用tokens[i]值大的换取能量。这样就可以使积分最大化。
1.首先进行排序
2.如果能量够的话,就换积分(这样是最划算的);能量不够的话,并且有积分,换取能量;其他情况就直接break(因为你的积分也不够,能量也不足以换取积分)
代码:
class Solution {
public int bagOfTokensScore(int[] tokens, int power) {
//贪心策略:如果能量够的话 就得分。不够的话 看看有没有分 换能量
Arrays.sort(tokens);
int res=0;
int left=0;
int right=tokens.length-1;
int score=0;
while(left<=right){
if(power>=tokens[left]){
score++;
power-=tokens[left++];
res=Math.max(res,score);
}else if(score>0){
score--;
power+=tokens[right--];
}else{
break;
}
}
return res;
}
}
三、分割两个字符串得到回文串
题意:
给定两个子串a,b;在相同的下标位置切割子串得到,preA sufA; preB sufB。
看preA+sufB或者preB+sufA能否构成回文串。
思路:
因为题目中要求是从相同的下标位置处切割。所以要找到能和b串后缀构成回文串的a串的最大前缀;(也就是图片中红色的位置)。
如果红色的位置越多,那么剩余部分判断回文串的长度就小了。
所以贪心的策略为:
1.尽可能多的去匹配a串前缀和b串的后缀
public boolean checkPalindromeFormationHelp(String a,String b){
int left=0;
int right=b.length()-1;
int len=0;
while(left<right&&a.charAt(left)==b.charAt(right)){
left++;
right--;
}
return idPalindrome(a,left,right)||idPalindrome(b,left,right);
}
2.然后看剩余的部分是否是回文子串。
public boolean idPalindrome(String s, int left, int right) {
while(left<right&&s.charAt(left)==s.charAt(right)){
left++;
right--;
}
return left>=right;
}
代码:
class Solution {
public boolean checkPalindromeFormation(String a, String b) {
// a前b后或者a后b前
return checkPalindromeFormationHelp(a, b) || checkPalindromeFormationHelp(b, a);
}
public boolean checkPalindromeFormationHelp(String a,String b){
int left=0;
int right=b.length()-1;
int len=0;
while(left<right&&a.charAt(left)==b.charAt(right)){
left++;
right--;
}
return idPalindrome(a,left,right)||idPalindrome(b,left,right);
}
public boolean idPalindrome(String s, int left, int right) {
while(left<right&&s.charAt(left)==s.charAt(right)){
left++;
right--;
}
return left>=right;
}
}
说明:
第一个函数中的||,是拿a还是b的前缀就行匹配。
第二个函数中的||,xxxxx
两个是不冲突的。