首页 > 试题广场 >

字母交换

[编程题]字母交换
  • 热度指数:5142 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

【编码题】字符串S由小写字母构成,长度为n。定义一种操作,每次都可以挑选字符串中任意的两个相邻字母进行交换。询问在至多交换m次之后,字符串中最多有多少个连续的位置上的字母相同?



输入描述:
第一行为一个字符串S与一个非负整数m。(1 <= |S| <= 1000, 1 <= m <= 1000000)


输出描述:
一个非负整数,表示操作之后,连续最长的相同字母数量。
示例1

输入

abcbaa 2

输出

2

说明

使2个字母a连续出现,至少需要3次操作。即把第1个位置上的a移动到第4个位置。
所以在至多操作2次的情况下,最多只能使2个b或2个a连续出现。 
import java.util.*;

public class Main{
    static int res = 1;
    public static void main(String[] args){
        
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        String str = input.split(" ")[0];
        int m = Integer.parseInt(input.split(" ")[1]);
        
        HashMap<Character, List<Integer>> map = new HashMap<>();
        char[] chars = str.toCharArray();
        int len = chars.length;
        
        for(int i = 0; i < len; i++){
            List<Integer> list = map.getOrDefault(chars[i], new ArrayList<>());
            list.add(i);
            map.put(chars[i], list);
        }
        
        for(int i = 0; i < len; i++){
            char c = chars[i];
            List<Integer> list = map.get(c);
            moveTogether(list, i, m);
            /*
            int lessCount = 0;
            for(int num : list){
                if(num < i){
                    lessCount++;
                }
                else{
                    break;
                }
            }
            int greatCount = list.size()-1-lessCount;
            for(int j = 0; j < lessCount; i++){
                int cur = list.get(j);

                // 现在这个节点的位置在cur,要移动到          (0 1 j 3 4 ... lessCount-1)i
                // lesscount-2的时候对应i-2
                // lesscount-1的时候对应i-1
                int target = i + j - lessCount;
                int times = 
            }
        }
*/
        
        
        
    }
                System.out.println(res);
        
  
    
        
    }
            // 在times步内,尽可能把list里面的数字移动到mid周围
        public static void moveTogether(List<Integer> list, int mid, int times){
            int len = list.size();
            int mid_index = 0;
            for(int i = 0; i < len; i++){
                if(list.get(i) == mid){
                    mid_index = i;
                    break;
                }
            }
            int left_index = mid_index-1;
            int right_index = mid_index+1;
            int count = 1;
            // mid为中心的左右边界
            int left_mid = mid-1;
            int right_mid = mid+1;
            while(times > 0){
                if(left_index < 0 && right_index >= len){
                    break;
                }
                
                // 看一下左边和右边哪个更近一点
                int left_dist;
                if(left_index < 0)    
                    left_dist = Integer.MAX_VALUE / 2;
                else    
                    left_dist = left_mid - list.get(left_index);
                int right_dist;
                if(right_index >= len)   {
                    right_dist = Integer.MAX_VALUE / 2;
                } 
                else {
                    right_dist = list.get(right_index) - right_mid; 
                }    
                   
                if(left_dist > right_dist){
                    // 右边靠更加近一点
                    if(times < right_dist)    break;
                    times -= right_dist;
                    right_mid++;
                    count++;
                    right_index++;
                }
                else{
                    if(times < left_dist)    break;
                    times -= left_dist;
                    left_mid--;
                    left_index--;
                    count++;
                }
            }
            res = Math.max(count, res);
        }
  
}

发表于 2021-01-18 21:20:46 回复(0)