leetcode 8

在这里插入图片描述
a^b = c
则b= c^a
a = c^b
两种方法,第二种方法相等于第一种的加速寻找最大的,用了前缀树,用了32位补码相关知识

public class MaxEor {
   public static int maxXorSubarray1(int[] arr){
       if(arr == null || arr.length == 0){
           return 0;
       }

       int[] eor = new int[arr.length];
       eor[0] = arr[0];
       for (int i = 0; i < arr.length; i++) {
           eor[i] = eor[i-1] ^arr[i];
       }
       //上述代码求出了0...1
       // 0...2    0...3   ...  的异或和
       int max = Integer.MIN_VALUE;
       //下面代码求的是0...j  1...j 2...j 3...j 根据异或和的性质i...j的异或和是eor[i-1]^eor[j]
       for(int j = 0; j<arr.length;j++){
           for (int i = 0; i <= j; i++) {
               max = Math.max(max,i==0?eor[j]:eor[j]^eor[i-1]);
           }
       }
       return max;
   }

   public static class Node{
       public Node[] nexts = new Node[2];
   }

   public static class NumTrie{
       public Node head = new Node();

       //把newNum加入前缀树
       //num是一个32位
       public void add(int newNum){
           Node cur = head;
           for(int move = 31;move>=0;move--){
              int path = ((newNum>>move)&1);//拿到第move位 只有0或者1
               //无路新建 右路复用
               cur.nexts[path] = cur.nexts[path] == null ? new Node():cur.nexts[path];
               cur = cur.nexts[path];
           }
       }

       //该结构收集一票数字,并且建好了前缀树
       //sum 和谁 ^ 最大的结果(把结果返回)
       public int maxXor(int sum){
           Node cur = head;
           int res=  0;
           for(int move = 31;move>=0;move--){
               //参数sum第move位是多少
               int path = (sum >> move) & 1;

               //贪心策略,如果是最高位,和原来一样,因为这样得到的是正数
               // ,如果不是最高位,取反,因为异或后是1
               int best = move == 31 ? path : (path^1);

               //收集从开始到当前位异或后的结果
               res |= (path ^ best) << move;

               cur = cur.nexts[best];
           }
           return res;
       }
   }

   public static int maxXorSubarray2(int[] arr){
       if(arr == null || arr.length == 0){
           return  0;
       }
       int max  = Integer.MAX_VALUE;
       int eor = 0;
       NumTrie numTrie = new NumTrie();
       numTrie.add(0);//一个数也没有 异或和是0
       for (int i = 0; i < arr.length; i++) {
          eor ^= arr[i]; //是0...i的异或和
          max = Math.max(max,numTrie.maxXor(eor));
          numTrie.add(eor);//只增加0...i的异或和,因为其他的都可以通过0...i获得  比如i...j的,,可以通过0...i-1,和0...j的异或和获得
       }
       return max;
   }
}

给定一个数组,对中间位置任意划分,最多能划分出多少个异或和为0的子数组
思路:假设答案法
蜜汁题目 理解不了。有机会再看 在这里插入图片描述

public class ExpressionNumber {

    public static boolean isVaild(char[] exp){
        if((exp.length & 1) == 0){
            return false;
        }
        for (int i = 0; i < exp.length; i+=2) {
            if((exp[i] != '1') && (exp[i]!='0')){
                return false;
            }
        }
        for (int i = 1; i < exp.length; i+=2) {
            if((exp[i] != '&') && (exp[i] != '|') && (exp[i]!='^')){
                return false;
            }
        }
        return true;
    }
    public static int num1(String express,boolean desired){
        if (express == null || express.equals("")) {
            return 0;
        }
        char[] exp = express.toCharArray();
        if(!isVaild(exp)){
            return 0;
        }

        return f(exp,desired,0,exp.length-1);
    }

    public static int f(char[] exp,boolean desired,int L,int R){
        if(L == R){
            if(exp[L] == '1'){
                return desired?1:0;
            }else {
                return desired?0:1;
            }
        }

        //略
        int res = 0;
        if(desired){
            for (int i = L+1; i < R; i+=2) {
                switch (exp[i]){
                    case '&':
                        res+=f(exp,true,L,i-1)*f(exp,true,i+1,R);
                }
            }
        }
        return res;
    }
}

在这里插入图片描述

public class JumpGame {
    public static int jump(int[] arr){
        if(arr == null || arr.length == 0){
            return 0;
        }
        int step = 0;
        int cur = 0;
        int next = 0;
        for (int i = 0; i < arr.length; i++) {
            if(cur < i){
                step++;
                cur = next;
            }
            next = Math.max(next,i + arr[i]);
        }
        return step;
    }
}

str中 至少切几刀,都是回文

public class PMinParts {

    public static int minParts(String s){
        if(s == null || s.length() == 0){
            return 0;
        }
        if(s.length() == 1){
            return 1;
        }
        char[] str = s.toCharArray();
        int N = str.length;
        boolean[][] isP = new boolean[N][N];
        for (int i = 0; i < N; i++) {
            isP[i][i] = true;
        }
        for (int i = 0; i < N - 1; i++) {
            isP[i][i+1] = str[i] == str[i+1];
        }
        for(int row = N-1;row >=0;row--){
            for(int col = row + 2;col < N;col++){
                isP[row][col] = str[row] == str[col] && isP[row+1][col-1];
            }
        }
        //isP[i][j]代表[i,j]位置是否是回文串
        int[] dp = new int[N+1];
        for(int i = 0;i <= N;i++){
            dp[i] = Integer.MAX_VALUE;//找最小值
        }
        dp[N] = 0;
        //dp[i]代表从i开始到最后 回文串最少切几刀

        for (int i = N-1; i >= 0 ; i++) {
            for(int end = i;end<N;end++){
                if(isP[i][end]){
                    dp[i] = Math.min(dp[i],i+dp[end+1]);
                }
            }
        }

        return dp[0];
    }


}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值