搜狗笔试题-正确答案的个数

题目描述:

  汪仔和他朋友,分别做选择题,选择题有 n 道,汪仔做的答案用 str1 表示,朋友做的答案用 str2 表示,现在给定一个 K 值,K 值指的是朋友的答案与真正的答案(这些题的真实答案,你不知道)相比较时,对的个数。求:小明的答案,与真实的答案相比较,最多能对几个?最少能对几个?

输入:

  n 表示题目个数,k 表示朋友的答案正确的个数,str1 表示汪仔的答案,str2 表示汪仔朋友的答案。

  返回值用给定的内部类表示。

 示例2:

输入:

  3, 1, "ABC", "DDD"

输出:

  [0, 2]

说明:汪仔最少对 0 道,最多对 2 道,因为朋友 "DDD" 对了 1 道,所以正确答案里面至少有一个 D,而汪仔一个 D 都没有,所以最多对 2 道。

思路一:

一拿到题,就想的是用枚举、DFS深搜遍历的方法,穷举正确答案,将穷举的正确答案,与汪仔朋友的答案比较,当朋友正确个数刚好为 K 时,我们可以假设这个答案就是有效的正确答案,再用这个穷举的答案与小明的答案挨个比较,将得到的正确个数与已知结果比较,比最小值小,则更新最小值;比最大值大,则更新最大值。

错误的方法:这种方法 没有AC!!!(时间复杂度太高了,4^n 的穷举情况,复杂度太高)

class Interval {
    int start;
    int end;
}

public class souGou1 {
    public static Interval interval = new Interval(); //保存结果的类对象
    public static void main(String[] args) {
        Interval res = solve(3,1,"ABC","DDD"); //测试数据
        System.out.println(res.start);
        System.out.println(res.end);
    }
    public static Interval solve (int n, int k, String str1, String str2) {
        char[] chars = new char[n]; //用来穷举的答案数组
        for(int i = 0; i < str1.length(); i++) chars[i] = 'A';
        interval.start = Integer.MAX_VALUE; //汪仔最少的答案个数, 初始设置为一个很大的数
        interval.end = 0; //汪仔最多的答案个数, 初始设置为一个很小的数
        if(str1.equals(str2)){ //当汪仔的答案与朋友的一模一样时,最小最大都为k
            interval.start = k;
            interval.end = k;
            return interval;
        }
        DFS(chars,str1.toCharArray(),str2.toCharArray(),k,0); //深搜穷举
        return interval;
    }
    public static void DFS(char[] chars, char[] str1, char[] str2, int k, int idx){
        //chars表示穷举的答案,str1汪仔的答案,str2朋友的答案,k 朋友对的个数,idx表示穷举到哪一个下标了
        if(idx == chars.length){ //穷举的一次答案
            int count = 0, ansCount = 0; // count 表示朋友的正确个数,ansCount表示汪仔的正确个数
            for(int i = 0; i < str2.length; i++){
                if(chars[i] == str2[i]) count++;
                if(chars[i] == str1[i]) ansCount++;
            }
            if(count != k) return; //当朋友的正确个数与题目给的 k 值不相等,说明这个穷举的答案无效,返回
            if (ansCount < interval.start) interval.start = ansCount;
            if(ansCount > interval.end) interval.end = ansCount;
            return;
        }
        chars[idx] = 'A'; // 当前的 idx 位置上,穷举 A,B,C,D 四个可能的答案
        DFS(chars,str1,str2,k,idx+1);
        if(interval.start == 0 && interval.end == chars.length) return; //减枝
        chars[idx] = 'B';
        DFS(chars,str1,str2,k,idx+1);
        if(interval.start == 0 && interval.end == chars.length) return; //减枝
        chars[idx] = 'C';
        DFS(chars,str1,str2,k,idx+1);
        if(interval.start == 0 && interval.end == chars.length) return; //减枝
        chars[idx] = 'D';
        DFS(chars,str1,str2,k,idx+1);
    }
}

但是:提交 OJ,显示通过率只有 40%,这种办法没有 AC !

思路二:

将汪仔的答案,与朋友的答案比较,记录他们的答案中,相同的个数 count利用这个 count 与 k 即可直接求得结果求最大值,当 k <= count 时,汪仔最多对: k + (n - count) 道;当 k > count 时,汪仔最多对:count + n - k 道。同理,求最小值,计算 k - (n - count) 的值,当结果 <= 0 时,最小值 = 0;当结果 > 0时,最小值 = k - (n - count) .  这个推导式有点绕,很不容易想明白。

正确方法:直接利用关系推导式,直接得出结果!

class Interval {
    int start;
    int end;
}

public class souGou1 {
    public static void main(String[] args) {
        Interval res = solve(3,3,"ABC","ABC"); //测试数据
        System.out.println(res.start);
        System.out.println(res.end);
    }
    public static Interval solve (int n, int k, String str1, String str2) {
        Interval res = new Interval();
        int count = 0, min, max; //正确的答案个数最小值、最大值
        for(int i = 0; i < n; i++){
            if(str1.charAt(i) == str2.charAt(i)) count++; //记录相等的个数 count
        }
        int tmp = k - (n - count);
        min = tmp <= 0? 0 : tmp; // 得到最小值
        if(k <= count) max = k + (n - count); // 最大值分类讨论
        else max = count + n - k;
        res.start = min; //写入对象中
        res.end = max;
        return res; // 返回结果
    }
}
原文地址:https://www.cnblogs.com/luo-c/p/13732861.html