【笔试强训】Week3:重排字符串,分组,DNA序列

文章目录

1. 重排字符串

重排字符串

题目描述

解题思路

贪心+构造

每次处理相同的字符,优先处理出现次数最多的字符

  1. 先统计所有字母的出现次数,并记录最大次数,最大次数决定了这个字符串能否重排
  2. 让次数最多之外的字符间隔一个空排列,当把偶数格子排列完,剩余奇数格子天然就是不相邻的。
  3. 能否重排:maxcnt>(n+1)/2时,不可以重排.

代码实现

java 复制代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        in.nextLine();
        String str = in.nextLine();
        char[] ss = str.toCharArray();
        int[] arr = new int[26];

        int max = 0;
        char maxchar = '0';

        for (int i = 0; i < n; i++) {
            arr[ss[i] - 'a']++;
            if (arr[ss[i] - 'a'] > max) {
                max = arr[ss[i] - 'a'];
                maxchar = ss[i];
            }
        }

        if (max > (n + 1) / 2) {
            System.out.println("no");
            return;
        } else {
            System.out.println("yes");
            char[] ans = new char[n];
            //先处理次数最多的字符
            int i = 0;
            while(max-- >0){
                ans[i]=maxchar;
                i+=2;
            }
            for (int j = 0; j < 26; j++) {
                if(arr[j]>0 && (char)(j+'a')!=maxchar){
                   while(arr[j]-- >0){
                        if(i>=n)
                            i=1;
                        ans[i] = (char)(j+'a');
                        i+=2;
                   }
                }
            }
            for(int j = 0;j<n;j++)
                System.out.print(ans[j]);
        }
    }
}

2. 分组

分组

题目描述

解题思路

暴力枚举 -> 二分查找

  1. 利用哈希表统计每一声部的人数
  2. 枚举最终的分配结果中,小组中最多的人数。
    • x表示小组最多的人数。计算对于每个声部按x分组会有多少组,统计m1+m2+...总和是否小于等于m。
    • 找到哈希表中最大的value,枚举的范围就是1,hmax,从1开始枚举,直到找到一个数可以满足check条件。

优化:二分查找

可以把对[1,hmax]的枚举优化为二分查找:[1,ret-1] check(x)>m [ret,right] check(x)<=m

  • 如果check(mid)为假,则证明当前的x太小,应该把left更新为mid+1
  • 如果check(mid)为真,证明当前的x符合条件,但不一定是最小的,right更新为mid

代码实现

  • 暴力枚举
java 复制代码
import java.util.*;

public class Main{
    
    static HashMap<Integer,Integer> hash = new HashMap<>();
    static int m,n;
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        m = in.nextInt();
        int[] a = new int[n];
        
        int hmax = 0;
        for(int i = 0;i<n;i++){
            a[i] = in.nextInt();
            if(!hash.containsKey(a[i]))
                hash.put(a[i],0);
            hash.put(a[i],hash.get(a[i])+1);
            hmax = Math.max(hmax,hash.get(a[i]));
        }
   
        for(int i = 1;i<=hmax;i++){
            if(check(i)){
                System.out.println(i);
                return;
            }
        }
        System.out.println(-1);

    }
    //判断最多人数为x时能否被分成x组
    static boolean check(int x){
        int g = 0;//统计能分成多少组
        for(int a:hash.values()){
            g += a/x + ((a%x==0)?0:1);
        }
        return g<=m;
    }
}
  • 二分查找
java 复制代码
import java.util.*;

public class Main{
    
    static HashMap<Integer,Integer> hash = new HashMap<>();
    static int m,n;
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        m = in.nextInt();
        int[] a = new int[n];
        
        int hmax = 0;
        for(int i = 0;i<n;i++){
            a[i] = in.nextInt();
            if(!hash.containsKey(a[i]))
                hash.put(a[i],0);
            hash.put(a[i],hash.get(a[i])+1);
            hmax = Math.max(hmax,hash.get(a[i]));
        }
        
        int left = 1;
        int right = hmax;
        while(left<right){
            int mid = (right-left)/2+left;
            if(check(mid))
                right = mid;
            else
                left = mid+1;
        }
        if(check(left))
            System.out.println(left);
        else
            System.out.println(-1);

    }
    //判断最多人数为x时能否被分成x组
    static boolean check(int x){
        int g = 0;//统计能分成多少组
        for(int a:hash.values()){
            g += a/x + ((a%x==0)?0:1);
        }
        return g<=m;
    }  
}

3. DNA序列

DNA序列

题目描述

解题思路

滑动窗口

字串长度固定为5,所以两个指针同时向右运动,可以用滑动窗口。

代码实现

java 复制代码
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str = in.nextLine();
        int len = in.nextInt();

        char[] ss = str.toCharArray();
        int n = ss.length;
        String  ans = " ";

        int l = 0;
        int r = 0;
        int count = 0;
        int max = 0;

        while(r<n){
            if(ss[r]=='C' || ss[r]=='G')
                count++;
            while(r-l+1>len){
                if(ss[l]=='C' || ss[l] == 'G')
                    count--;
                l++;
            }
            if(r-l+1==len && count>max){
                max = count;
                ans = str.substring(l,r+1);
            }
            r++;
        }
        System.out.println(ans);
    }
}
相关推荐
aaaameliaaa32 分钟前
指针之总结
c语言·笔记·算法
宵时待雨1 小时前
优选算法专题9:哈希表
数据结构·算法·散列表
gwf2161 小时前
磨损均衡算法(Wear Leveling)——SSD如何让每块闪存“公平退休“?
运维·数据库·人工智能·python·嵌入式硬件·算法·智能硬件
noipp1 小时前
推荐题目:洛谷 P6231 [JSOI2013] 公交系统
c语言·数据结构·c++·算法·游戏·洛谷·luogu
c238561 小时前
C/C++每日一练6
c语言·c++·算法
AI小码2 小时前
把动作「画」给视频世界模型,跨本体双向推演,李飞飞参与
大数据·人工智能·算法·ai·大模型·音视频·编程
KaMeidebaby3 小时前
卡梅德生物技术快报|bli亲和力检测gst:告别批量跑胶:BLI实时酶切监测技术加速GST融合蛋白下游流程优化
前端·网络·数据库·人工智能·算法
alphaTao4 小时前
LeetCode 每日一题 2026/7/20-2026/7/26
算法·leetcode
青山木7 小时前
Hot 100 ---腐烂的橘子
java·数据结构·后端·算法·leetcode·广度优先
未来之窗软件服务7 小时前
计算机考试-快速排序—东方仙盟
数据结构·算法·排序算法·仙盟创梦ide·东方仙盟