395. 至少有 K 个重复字符的最长子串
题目
给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。
示例 1:
输入:s = "aaabb", k = 3
输出:3
解释:最长子串为 "aaa" ,其中 'a' 重复了 3 次。
示例 2:
输入:s = "ababbc", k = 2
输出:5
解释:最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 3 次。
思路
如果字符串的某个字符出现的总次数小于k,那么这个字符不可能出现在最后的答案里,所以可以采用分治的思想。每次都遍历字符串,找到第一个不符合条件的字符,然后以这个字符为中心,把原来的字符串拆成若干个子字符,如原来的字符串是aabedfbcd,目标字符是b,那么被拆成了aa、edf、cd。然后进行递归即可满足要求。
代码
class Solution {
public int longestSubstring(String s, int k) {
int n=s.length();
return dfs(0,n-1,s,k);
}
public int dfs(int l,int r,String s,int k){
int[] count=new int[26];
for(int i=l;i<=r;i++){
count[s.charAt(i)-'a']++;
}
int split=-1;
for(int i=0;i<26;i++){
if(count[i]!=0 && count[i]<k){
split=(char)(i+'a');
break;
}
}
if(split==-1) return r-l+1;
int start=l;int res=0;
while(start<=r){
while(start<=r && s.charAt(start)==split){
start++;
}
if(start>r) break;
int ll=start;
while(start<=r && s.charAt(start)!=split){
start++;
}
int rr=dfs(ll,start-1,s,k);
res=Math.max(res,rr);
}
return res;
}
}
1217. 玩筹码
题目
数轴上放置了一些筹码,每个筹码的位置存在数组 chips 当中。
你可以对 任何筹码 执行下面两种操作之一(不限操作次数,0 次也可以):
将第 i 个筹码向左或者右移动 2 个单位,代价为 0。
将第 i 个筹码向左或者右移动 1 个单位,代价为 1。
最开始的时候,同一位置上也可能放着两个或者更多的筹码。
返回将所有筹码移动到同一位置(任意位置)上所需要的最小代价。
示例 1:
输入:chips = [1,2,3]
输出:1
解释:第二个筹码移动到位置三的代价是 1,第一个筹码移动到位置三的代价是 0,总代价为 1。
示例 2:
输入:chips = [2,2,2,3,3]
输出:2
解释:第四和第五个筹码移动到位置二的代价都是 1,所以最小总代价为 2。
思路
奇数位置到奇数位置 偶数位置到偶数位置,这两种情况的代价是0,
所以总有办法把所有的位置放到相邻的两堆上,一堆奇数位置,一堆偶数位置,然后比较哪堆个数少就好了。
代码
class Solution {
public int minCostToMoveChips(int[] position) {
int odd=0;
int even=0;
for(int i:position){
if((i&1)==1) odd++;
else even++;
}
return Math.min(odd,even);
}
}