【笔试】2020年3月20号阿里笔试

输入10个int表示10种牌个数,可以打单牌(1),对子(11),顺子(12345), 连对(112233),求最少几次可以打完所有牌

(笔试时只通过了10%,现在重新编写将输出出牌次数改成输出出牌情况,方便大家理解以及帮助我纠错,注意:只经过我自己的测试,不一定能ac

public static void main(String[] args) {

    //10种牌,输入每种牌的张数
    Scanner sc = new Scanner(System.in);
    int n = 10;
    //测试
//        int[] arr = new int[]{1,2,2,2,1,1,1,2,1,2};
//        int[] arr = new int[]{1,1,1,2,2,2,2,2,1,1};
    int[] arr = new int[n];
    for(int i = 0; i < n; i++)
        arr[i] = sc.nextInt();

    //打印最快出牌情况
    List<List<Integer>> res = dfs(arr,0);
    for(List<Integer> lst : res)
        System.out.println(lst);

    //打印最快出牌次数
    System.out.println(res.size());

}

public static List<List<Integer>> dfs(int[] arr, int index){
    if(index>=arr.length) return new ArrayList<>();
    if(arr[index]==0) return dfs(arr,index+1);

    //打双牌
    List<List<Integer>> res = getMincount(arr,index,1,2);  //从index开始num种牌,每种牌至少有count张

    //打单牌
    List<List<Integer>> res1 = getMincount(arr,index,1,1);
    if(res.isEmpty()||(res1.size()!=0&&res.size()>res1.size())) res=new ArrayList<>(res1);

    //打顺子
    res1 = getMincount(arr,index,5,1);
    if(res.isEmpty()||(res1.size()!=0&&res.size()>res1.size())) res=new ArrayList<>(res1);

    //打连对
    res1 = getMincount(arr,index,3,2);
    if(res.isEmpty()||(res1.size()!=0&&res.size()>res1.size())) res=new ArrayList<>(res1);

    return res;
}

/**
 * @param arr  牌数
 * @param index 从index开始
 * @param num   打连续num种牌
 * @param count  每张牌打count张
 * @return
 */
private static List<List<Integer>> getMincount(int[] arr, int index,int num, int count){

    List<List<Integer>> reslist = new ArrayList<>();

    //判断一下是否可以出牌
    if(arr.length-index<num) return new ArrayList<>();
    List<Integer> lst = new ArrayList<>();
    for(int k=index;k<index+num;k++) {
        lst.add(k);
        if (arr[k] < count)
            return new ArrayList<>();
    }
    reslist.add(lst);

    //出牌
    operate(arr,index,num,-1*count);
    //dfs
    reslist.addAll(dfs(arr, index));
    //回溯
    operate(arr,index,num,count);
    return reslist;
}

private static void operate(int[] arr, int index,int num,int add){
    if(arr.length-index<num) return;
    int end = index+num;
    while (index<end){
        arr[index]+=add;
        index++;
    }
}

输入一个正整数n和n行升序的字符串,可以进行任意个字符串拼接,求最长升串;

(笔试时没来得及保存就到点系统交卷了,所以,嗯)

public static void main(String[] args) {
    //输入
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    sc.nextLine();
    List<String> list=new ArrayList<>();
    for(int i = 0; i < n; i++)
        list.add(i, sc.nextLine());

    //lambda排序,按首字母和字符串长度排序
    list.sort((o1, o2) -> {
        if (o1.charAt(0) == o2.charAt(0))
            return o2.length() > o1.length() ? 1 : 0;
        else
            return o2.charAt(0) < o1.charAt(0) ? 1 : -1;
    });

    //dp
    int[] dp = new int[n];
    dp[0]=list.get(0).length();
    int res = 0;
    for(int i=1;i<n;i++){
        //首字母排序后拼接的状态方程:
        //以第i个字符串结束的最长字串长度=它的长度+前面能够拼接的最长字串的长度
        int pre=0;
        for(int j=i-1;j>=0;j--){
            if(list.get(i).charAt(0)<list.get(j).charAt(list.get(j).length()-1)) continue;
            pre = Math.max(pre,dp[j]);
        }
        dp[i] = pre+list.get(i).length();
        res = Math.max(res,dp[i]);
    }

    System.out.println(res);

}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值