2021届秋招--贝壳笔试--给出或运算最大的子序列的最短长度

题目:

给定一个正整数数组,求或运算最大时候的最短序列。

示例:

输入: 1  2 3

输出:1

解释:1 2或运算是 3,1 2 3或运算是3,3自己也是3,最后一个长度为1,输出1.

运算:1|1 = 1,1|0 = 1,0|0 = 0

public class Num3 {

    public static int getNum(int n, long[] numsArr){
        if (n == 0) return 0;
        int[] indexNum = new int[32];
        long maxVal = numsArr[0];
        long tempMaxVal = numsArr[0];
        int maxLen = 1;
        int tempMaxLen = 1;
        String tempBinZero = Long.toBinaryString(numsArr[0]);
        int lenTempBinZ = tempBinZero.length();
        int tempIndexBinZ = lenTempBinZ;
            while (tempIndexBinZ > 0){
                tempIndexBinZ--;
                if (tempBinZero.charAt(tempIndexBinZ) == '1'){
                    indexNum[lenTempBinZ-1-tempIndexBinZ]++;
                }
            }
        for (int i = 1; i < n; ++i){
            String tempBin = Long.toBinaryString(numsArr[i]);
            int lenTempBin = tempBin.length();
            int tempIndexBin = lenTempBin;
            while (tempIndexBin > 0){
                tempIndexBin--;
                if (tempBin.charAt(tempIndexBin) == '1'){
                    indexNum[lenTempBin-1-tempIndexBin]++;
                }
            }
            long indexAndPre = numsArr[i] | tempMaxVal;
            int temIndexLen = tempMaxLen;
            for (int j = i - temIndexLen; j < i; ++j){
                boolean flag = false;//true是正常,false是删除
                String tempJBin = Long.toBinaryString(numsArr[j]);
                int lenTempJBin = tempJBin.length();
                int tempIndexJBin = lenTempJBin;
                int[] indexNumJB = new int[32];
                while (tempIndexJBin > 0){
                    tempIndexJBin--;
                    if (tempJBin.charAt(tempIndexJBin) == '1'){
                        if (indexNum[lenTempJBin-1-tempIndexJBin] == 1){
                            flag = true;
                            break;
                        }
                        indexNumJB[lenTempJBin-1-tempIndexJBin] = 1;
                    }
                }
                if (!flag){
                    tempMaxLen--;
                    for (int k = 0; k < 32; ++k){
                        if (indexNumJB[k] == 1){
                            indexNum[k]--;
                        }
                    }
                }else {
                    break;
                }
                for (int k =0; k < 32; ++k){
                    indexNumJB[k] = 0;
                }
            }
            tempMaxLen++;
            tempMaxVal = indexAndPre;
            if (maxVal < tempMaxVal){
                maxVal = tempMaxVal;
                maxLen = tempMaxLen;
            }else if(maxVal == tempMaxVal){
                maxLen = Math.min(maxLen, tempMaxLen);
            }
        }
        return maxLen;
    }

    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int i = 0;
        long[] numsArr = new long[n];
        while ( i < n){
            numsArr[i] = in.nextLong();
            ++i;
        }
        System.out.println(getNum(n, numsArr));
    }
}

思路详述:这题很明显是用到动态规划(不推荐暴力破解)。当遍历到第k数时有下列情况发生:

首先说明:

记录目前最大的或值maxVal和最短长度maxLen。

记录以前一个节点结尾的最大tempMaxVal和最短长度temMaxLen。

长度为32的Int数组intNum[] 用来记录以前一个节点结尾的最大tempMaxVal这个长度为temMaxLen序列中每位上的1出现的次数。

流程:

定义一个临时变量indexAndPre表示把第k个或运算到tempMaxVal后的值。(更新intNum)

目的:尽可能值不变,缩短长度。所以要从这个序列的起始位置(k-temMaxLen)开始向后遍历。得到遍历值的长度为32int[]数组的内容,同时检查当该值的数值下标对应值为1时,intNum上对应为数是否为1(如果为1,则删了这个数,temMax就变小了,如果大于1说明别的数字在这个位上也有1,可以掩盖他,可以删)。如果都不是1,那就可以删除这个数,temMaxLen--,对应的intNum--。如果有一位是一,那就跳出循环,不能删。(记得最后temMaxLen++)

完成上述后要对最大值和长度进行更新,这个好说。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值