learn--algorithm

60 阅读11分钟
  1. 相同的树
public boolean isTreeSame(TreeNode root1, TreeNode root2) {
        if (root1 == null && root2 == null) {
            return true;
        }
        if (root1 == null || root2 == null) {
            return false;
        }
        if (root1.val != root2.val ) {
            return false;
        }
        return isTreeSame(root1.left, root2.left) && isTreeSame(root1.right, root2.right);
    }
  1. 恢复二叉搜索树
    public void recoverTree(TreeNode root) {
        List<Integer> nums = new ArrayList<Integer>();
        inorder(root, nums);
        int[] values = findvalue(nums);
        recover(root, values, 2);

    }


    public void inorder(TreeNode root, List<Integer> nums ) {
        if (root == null) {
            return;
        }
        inorder(root.left, nums);
        nums.add(root.val);
        inorder(root.right, nums);
    }

    public int[] findvalue(List<Integer> nums) {
        int index1 = -1, index2 = -1;

        for (int i = 0; i < nums.size() -1; i++) {
            if (nums.get(i) > nums.get(i+1)) {
                index2 = i + 1;
                if (index1 == -1) {
                    index1 = i;
                } else {
                    break;
                }
            }
        }
        return new int[] {nums.get(index1), nums.get(index2)};
    }


    public void recover(TreeNode root, int[] values, int count) {
        int x = values[0], y = values[1];
        if (root == null) {
            return;
        }
        if (root.val == x || root.val ==y) {
            root.val = root.val ==x  ? y : x;
            if(--count == 0) {
                return;
            }
        }
        recover(root.left, values, count);
        recover(root.right, values, count);
    }

102.验证二叉搜索树


    public boolean isBTS(TreeNode root, int lower, int high) {
        if (root == null) {
            return true;
        }
        if (root.val >= high || root.val <= lower ) {
            return false;
        }
        return isBTS(root.left,lower, root.val) && isBTS(root.right, root.val, high);
    }
  1. 交错字符串
s1s2 = s3

f(i,j) =  s2[j] == s3[i+j] && f(i, j-1)

s2s1 = s3

f(i,j) = s1[i] == s3[i+j] && f(i-1, j)


public boolean isInterleave(String s1, String s2, String s3) {
    int n = s1.length();
    int m = s2.length();
    int s = s3.length();
    if (n + m != s) {
        return false;
    }
    boolean [][] f = new boolean[n+1][m+1];
    f[0][0] = true;

    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <=m; j++) {
            int p = i + j -1;
            if (i > 0) {
                f[i][j] = f[i][j] || f[i -1][j] && s3.charAt(p) == s1.charAt(i-1);
            }
            if (j > 0) {
                f[i][j] = f[i][j] || f[i][j-1] && s3.charAt(p) == s2.charAt(j-1);
            }
        }
    }
    return f[n][m];
}

100.不同的二叉搜索树

1~n,n长度
G[n]:表示长度为n的树的可能性
f(i,n)表示根节点为i,长度为n的树的可能性

G(n) = f(i,n) 之和i=0
f(i,n) = G(i-1) * G(n-i)
转换为:
G(n) = G(i-1) * G(n-i) 之和i =0

public int numTress(int n) {
    int[] G = new int[n +1];
    G[0] = 1;
    G[1] = 1;

    for (int i = 2; i <= n; i++) {
        for (int j = 1; j <= i; j++) {
            G[i] += G[j-1] * G[i -j];
        }
    }
    return G[n];
}
  1. 不同的二叉搜索树II
    i为根节点则:
    左子树: 0 ~ i-1 
    右子树: i+1 ~ n

    public List<TreeNode> generaTress(int start, int end) {
        List<TreeNode> allTress = new LinkedList<TreeNode>();
        if (start > end) {
            allTress.add(null);
            return allTress;
        }

        for (int i = start; i <= end; i++) {
            List<TreeNode> leftTree = generaTress(start, i -1);
            List<TreeNode> rightTree =  generaTress(i +1, end);

            for (TreeNode left : leftTree) {
                for (TreeNode right: rightTree) {
                    TreeNode curr = new TreeNode();
                    curr.val = i;
                    curr.left = left;
                    curr.right = right;
                    allTress.add(curr);
                }
            }
        }
        return allTress;
    }
  1. 树的中序遍历
中序遍历: 左子树--根--右子树

public List<Integer> treeMidum(TreeNode root) {
    List<Integer> ans = new ArrayList<Integer>();
    midumOrder(root, ans);
    return ans;
}

public void midumOrder(TreeNode root, List<Integer> ans) {
    if (root == null) {
        return;
    }
    midumOrder(root.left, ans);
    ans.add(root.val);
    midumOrder(root.right, ans);
}

97.复原ip

给一个字符串,复原所有可能的ip

1. segment[4] 
2. dfs 
3. 如果是0, 则作为一个ip位



public List<String> restoreIp(String str) {
        int SEG_COUNT = 4;
        int[] segments = new int [SEG_COUNT];

        List<String> ans = new ArrayList<String>();

        dfs(str, 0, 0 ,segments, ans);
        return ans;
    }

    public void dfs(String str, int segmentId, int segmentStart, int[] segments, List<String> ans ) {
        if (segmentId == 4) {
            if (segmentStart == str.length()) {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < 4; i++) {
                    sb.append(segments[i]);
                    if (i != 3) {
                        sb.append(".");
                    }
                }
                ans.add(sb.toString());
            }
            return;
        }

        if (segmentStart == str.length()) {
            return;
        }

        if (str.charAt(segmentStart)  == '0' ) {
            segments[segmentId] = 0;
            dfs(str, segmentId + 1, segmentStart + 1, segments, ans);
            return;
        }

        int abbr  = 0;
        for (int segmentEnd = segmentStart; segmentEnd < str.length(); segmentEnd++) {
            abbr = abbr * 10 + str.charAt(segmentEnd) - '0';
            if (abbr > 0 && abbr < 256) {
                segments[segmentId] = abbr;
                dfs(str, segmentId + 1, segmentEnd +1, segments, ans);
            } else {
                break;
            }
        }
    }
  1. 反转链表II
 public LinkNode resver1(LinkNode head, int left, int right) {
        LinkNode dumpHead = new LinkNode(0, null);
        dumpHead.next = head;
        LinkNode pre = dumpHead;
        for (int i = 0; i < left -1;i++) {
            pre = pre.next;
        }
        LinkNode curr = pre.next;
        LinkNode next;
        for (int i = 0; i < right - left; i++) {
            next = curr.next;
            curr.next = next.next;
            next.next = pre.next;
            pre.next =  next;
        }
        return dumpHead.next;
    }
  1. 解码方法
    f[i] = f[i-1] + f[i -2]

  public int numberEncoding(String str) {
      int n = str.length();

      int [] f = new int[n +1];
      f[0] = 1;

      for (int i = 1; i <=n; i++) {
          if (str.charAt(i- 1) != '0') {
              f[i] += f[i -1];
          }
          if (i > 1 && str.charAt(i -2) != '0' &&   ((str.charAt(i -2) - '0') * 10 + str.charAt(i-1) - '0')  <= 26 ) {
              f[i] += f[i -2];
          }
      }
      return f[n];
  }

94.子集ll

 public List<List<Integer>> subSeque(int[] nums) {
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        List<Integer> t = new ArrayList<Integer>();
        Arrays.sort(nums);
        dfs(false, 0, nums, ans, t);
        return ans;
    }



    public void dfs(boolean flag, int cur, int[] nums, List<List<Integer>> ans, List<Integer> t) {
        if (cur == nums.length) {
            ans.add(new ArrayList<Integer>(t));
            return;
        }
        dfs(false, cur +1, nums, ans, t);
        if (!flag && cur > 0 && nums[cur] == nums[cur -1]) {
            return;
        }
        t.add(nums[cur]);
        dfs(true, cur +1, nums, ans, t);
        t.remove(t.size() -1);

    }
  1. 格雷编码
 2 = 4
 00 = 0  00^10 = 10
 01 = 1  01^10 = 11
 10 = 2  10^11 = 01
 11 = 3  11^11=  00

 1^1 = 0
 0^0 = 0
 0^1 = 1
 1^0 = 1

public List<Integer> graycode(int n) {
     List<Integer> res = new ArrayList<Integer>();

     for (int i = 0; i < (1 << n); i++ ) {
         res.add( (i >> 1) ^ i );
     }
     return res;
 }
  1. 合并两个有序数组

public void merger(int[] num1, int m, int[] num2, int n) {
    int [] sort  = new int[m +n];
    int p1 = 0, p2 = 0;

    int cur;
    while(p1 < m || p2 < n) {
        if (p1 == m) {
            cur = num2[p2++];
        } else if (p2 == n) {
            cur = num1[p1++];
        } else if (num1[p1] < num2[p2]) {
            cur = num1[p1++];
        } else {
            cur = num2[p2++];
        }
        sort[p1 + p2 -1] = cur;
    }

    for (int i = 0; i < m +n ; i++) {
        num1[i] = sort[i];
    }
}

91.扰乱字符串

动态规划核心方程:

f(s1, s2) = (f[s1(0, i)][s2(0,i)] && f[s1(i, n -i)][s2(i, n-i)] ) || (f[s1(0,i)][s2(n -i,i)] && f[s1(i, n -1)][s2(0, n -i)])

res[l1][l2][i] && res[l1 + i][l2 +i][k -i]) || (res[l1][l2 + k -i][i] & res[l1 + i][l2][k-i])

k代表长度, i代表截断


 public boolean isScramble(String s1, String s2) {
        if (s1.length() != s2.length()) {
            return false;
        } 
        int n = s1.length();
        // [s1的第几个字符][s2的第几个字符][长度]
        boolean [][][] res = new boolean[n][n][n +1];
        // 只有一个字符
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                res[i][j][1] = s1.charAt(i) == s2.charAt(j);
            }
        }

        for (int k = 2; k <= n; k++ ) {
            for (int l1 = 0; l1 <= n -k; l1++) {
                for (int l2 =0; l2 <= n -k; l2++) {
                    for (int i = 1; i < k ; i++) {
                        if (  (res[l1][l2][i] && res[l1 + i][l2 +i][k -i]) || (res[l1][l2 + k -i][i] & res[l1 + i][l2][k-i]) ) {
                            res[l1][l2][k] = true;
                        }
                    }
                }
            }
        }
        return res[0][0][n];
}

90.分隔链表

 public LinkNode  splitLink(LinkNode head, int x) {
        LinkNode smallHead = new LinkNode(0, null);
        LinkNode small = smallHead;
        LinkNode largeHead = new LinkNode(0, null);
        LinkNode large = largeHead;

        while(head != null) {
            if (head.value < x) {
                small.next = head;
                small = small.next;
            } else {
                large.next  = head;
                large = large.next;
            }
            head = head.next;
        }
        large.next = null;
        small.next = largeHead.next;
        return smallHead.next;
    }
  1. 柱状图中最大的矩形
找出某个元素的左右边界,左右边界大于这个元素的高度

 利用栈来找


    public int maxArea1(int [] nums) {
        int n = nums.length;
        int[] left = new int[n];
        int[] right = new int[n];

        Deque<Integer> stack = new ArrayDeque<Integer>();

        for (int i = 0; i < n; i++) {
            while(!stack.isEmpty() && nums[stack.peek()] >= nums[i] ) {
                stack.poll();
            }
            left[i] = stack.isEmpty() ? -1 : stack.peek();
            stack.push(i);
        }
        stack.clear();

        for (int i = n -1; i > 0; i--) {
            while(!stack.isEmpty() && nums[stack.peek()] >= nums[i] ) {
                stack.poll();
            }
            right[i] = stack.isEmpty() ? n : stack.peek();
            stack.push(i);
        }

        int ans = 0;
        for (int i = 0; i < n; i++) {
            ans = Math.max(ans, (right[i] - left[i] - 1) * nums[i]);
        }
        return ans;
    }

  1. 删除排序链表中的重复元素
    public LinkNode repeatSveOne(LinkNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        LinkNode node = head;

        while (node != null && node.next != null) {
            int value  = node.value;
            if (value == node.next.value) {
                while (node.next != null && value == node.next.value) {
                    node.next = node.next.next;
                }
            } else {
                node = node.next;
            }
        }

        return head;
    }
  1. 删除排序链表中的重复元素ll
    要注意设置一个哑元素  LinkNode node = new LinkNode(0, head);

    public LinkNode deleteRepeat(LinkNode head) {
        if (head == null || head.next == null) {
            return head;
        }

        LinkNode node = new LinkNode(0, head);
        LinkNode curr  = node;


        while (curr.next != null && curr.next.next != null) {
            if (curr.next.value == curr.next.next.value) {
                int value = curr.next.value;
                while (curr.next != null && value == curr.next.value) {
                    curr.next = curr.next.next;
                }
            } else {
                curr = curr.next;
            }
        }
        return node.next;
    }

  1. 搜索旋转排序数组ll
二分法
  1.考虑数组为空
  2.考虑数组只有一个
  3.考虑旋转后刚好左右边界等于计算出来的Mid
  4.mid等于target值 
  5. 考虑左边有序或者右边有序(总有一半是有序的)

  public boolean equalsTarget(int[] nums, int target) {
      int n = nums.length;
      if (n == 0) {
          return false;
      }
      if (n == 1) {
          return nums[0] == target;
      }
      int l = 0;
      int r = n -1;
      while (l < r) {
          int mid = (l + r)/2;
          if (nums[mid] == target) {
              return true;
          }
          if (nums[mid] == nums[l] && nums[mid] == nums[r]) {
              r--;
              l++;
          } else if (nums[mid] >= nums[l]) {
              if (nums[l] <= target &&  target < nums[mid]) {
                  r = mid -1;
              } else {
                  l = mid + 1;
              }
          } else {
              if (nums[r] < target && target < nums[n -1]) {
                  l = mid + 1;
              } else {
                  r = mid -1;
              }
          }
      }
      return false;
  }
  
  1. 番外 删除最小的K个数

   public int[] mink(int [] nums, int k) {
        int n = nums.length;
        if (n < k) {
            return nums;
        }
        Queue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>() {
            @Override
            public int compare(Integer num1, Integer num2) {
                return num2 - num1;
            }
        });

        for (int i = 0; i < k; i++) {
            queue.offer(nums[i]);
        }

        for (int i = k; i < n ; i++) {
            if (queue.peek() > nums[i]) {
                queue.poll();
                queue.offer(nums[i]);
            }
        }

        int [] res = new int[k];

        for (int i = 0; i < k; i++) {
            res[i] = queue.poll();
        }
        return res;
    }
  1. 删除有序数组中的重复项 ll
    public int arrayLen(int [] nums) {
        int len = nums.length;
        if (len <= 2) {
            return len;
        }
        int slow = 2, fast = 2;
        while (fast < len) {
            if (nums[slow -2] != nums[fast]) {
                nums[slow] = nums[fast];
                slow++;
            }
            fast++;
        }
        return slow;
    }

83.单词搜索

public boolean searchWord(char[][] board, String word) {
        int n = board.length;
        int m = board[0].length;

        boolean[][] vis = new boolean[n][m];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                boolean flag = check(board, word, i, j, 0, vis);
                if (flag) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean check(char[][] board, String word, int i, int j, int k, boolean[][] vis) {
        if (board[i][j] != word.charAt(k)) {
            return false;
        } else if (k == word.length() -1) {
            return true;
        }

        vis[i][j] = true;
        boolean result = false;
        int[][] direction = { {0, -1}, {0, 1}, {1, 0}, {-1, 0} };
        for (int[] dire: direction) {
            int newi = i + dire[0];
            int newj = j + dire[1];

            if (newi >= 0 && newi < board.length && newj >= 0 && newj < board[0].length ) {
                boolean flag = check(board, word, newi, newj, k +1, vis);
                if (flag) {
                    result = true;
                    break;
                }
            }
        }
        vis[i][j] = false;
        return result;
    }

  1. 子集
    回溯算法

 public List<List<Integer>> allChild(int [] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        List<Integer> path = new ArrayList<Integer>();
        dfs1(nums, 0, res, path);
        return res;
    }

    public void dfs1(int[] nums, int start, List<List<Integer>> res, List<Integer> path) {

        res.add(new ArrayList<Integer>(path));

        for (int i = start;  i < nums.length; i++) {
            path.add(nums[i]);
            dfs1(nums, i + 1, res, path);
            path.remove(path.size() - 1 );
        }
    }

  1. 组合
    回溯算法

    public List<List<Integer>> zuhe(int n, int k) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        List<Integer> path = new ArrayList<Integer>();
        dfs(n, k, 1, path, res);
        return res;
    }

    public void dfs(int n, int k, int start, List<Integer> path,  List<List<Integer>> res) {
        if (path.size() == k) {
            res.add(new ArrayList<Integer>(path));
            return;
        }

        for (int i = start; i <= n; i++) {
            path.add(i);
            dfs(n, k, i +1, path, res);
            path.remove(path.size() - 1);
        }
    }
  1. 最小覆盖子串
    滑动窗口

  public String minContains(String s1, String t1) {
        Map<Character, Integer> t1map = new HashMap<>();
        Map<Character, Integer> s1map = new HashMap<>();

        for (int i = 0; i < t1.length(); i++) {
            t1map.put(t1.charAt(i), t1map.getOrDefault(t1.charAt(i) , 0) + 1);
        }

        int l = 0, r = -1;
        int ansl = -1, ansr = -1;
        int slen = s1.length();
        int len = Integer.MAX_VALUE;

        while(r < slen) {
            ++r;
            if (r < slen &&  t1map.containsKey(s1.charAt(r))) {
                s1map.put(s1.charAt(r),  s1map.getOrDefault(s1.charAt(r), 0) + 1 );
            }

            while (check(t1map, s1map) &&  l <= r) {
                if (r -l + 1 < len) {
                    len = r - l + 1;
                    ansl = l;
                    ansr = l + len;
                }
                if (s1map.containsKey(s1.charAt(l)) ) {
                    s1map.put(s1.charAt(l), s1map.getOrDefault(s1.charAt(l), 0 ) -1);
                }
                ++l;
            }
        }
        return ansl == -1 ? "" : s1.substring(ansl, ansr);
    }

    public boolean check(Map<Character, Integer> t1Map, Map<Character, Integer> s1Map) {
        Iterator it = t1Map.entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            Character key = (Character) entry.getKey();
            int value = (int)entry.getValue();
            if (s1Map.getOrDefault(key, 0) < value) {
                return false;
            }
        }
        return true;
    }

  1. 颜色分类
 public void  colorSort(int [] nums) {

        int prt = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == 0) {
                int temp =  nums[prt];
                nums[prt]  = nums[i];
                nums[i] = temp;
                prt++;
            }
        }

        for (int i = prt; i < nums.length; i++) {
            if (nums[i] == 1) {
                int temp = nums[prt];
                nums[prt] = nums[i];
                nums[i] = temp;
                prt++;
            }
        }
    }
  1. 搜索二维矩阵

 public boolean searchNums(int [][] nums, int target) {
        int index = searchRow(nums, target);
        if (index < 0) {
            return false;
        }
        return searchNum(nums[index], target);
    }

    public int searchRow(int [][] nums, int target) {
        int low = -1;
        int high = nums.length - 1;

        while(low < high) {
            int mid = (high  - low + 1) / 2 + low;
            if (nums[mid][0] < target ) {
                low = mid;
            } else {
                high = mid -1;
            }
        }
        return low;
    }

    public boolean searchNum(int [] nums, int target) {
        int low = 0;
        int high = nums.length;

        while(low <= high) {
            int mid = (high - low ) / 2 + low;
            if (nums[mid] == target) {
                return true;
            } else if (nums[mid] < target) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return false;
    }
  1. 矩阵置零
    public int[][] setZeros(int [][] nums) {
        int n = nums.length;
        int m = nums[0].length;

        boolean [] row = new boolean[n];
        boolean [] col = new boolean[m];

        for (int i = 0; i < n ; i++) {
            for (int j = 0; j < m; j++) {
                if (nums[i][j] == 0) {
                    row[i] = col[j] = true;
                }
            }
        }

        for (int i = 0; i < n ; i++) {
            for (int j = 0; j < m; j++) {
                if (row[i] || col[j]) {
                    nums[i][j] = 0;
                }
            }
        }
        return nums;
    }
  1. 编辑距离
    public int editDistant(String word1, String word2) {
        int m = word1.length();
        int n = word2.length();

        int[][] dp = new int[m + 1][n + 1];

        for (int i = 0; i < m +1 ; i++) {
            dp[i][0] = i;
        }
        for (int j = 0; j < n+1; j++) {
            dp[0][j] = j;
        }

        for (int i = 1; i < m +1; i++) {
            for (int j = 1; j < n +1; j++) {
                int left = dp[i -1][j] +  1;
                int down = dp[i][j-1] + 1;
                int left_down = dp[i-1][j-1];
                if (word1.charAt(i-1) != word2.charAt(j-1)) {
                    left_down += 1;
                }
                dp[i][j] = Math.min(left, Math.min(down, left_down));
            }
        }
        return dp[m][n];
    }

  1. 简化路径
 public String simplePath(String path) {
        String [] nums = path.split("/");

        Deque<String> stack = new ArrayDeque<String>();

        for (String name : nums) {
            if (name.equals("..")) {
                if (!stack.isEmpty()) {
                    stack.pollLast();
                }
            } else if(name.length() > 0 && !name.equals(".")){
                stack.offerLast(name);
            }
        }

        StringBuilder sb = new StringBuilder();

        if (stack.isEmpty()) {
            sb.append("/");
        } else {
            while(!stack.isEmpty()) {
                sb.append("/");
                sb.append(stack.pollFirst());
            }
        }
        return sb.toString();
    }
  1. 爬楼梯
    public int floor(int n) {
        int q = 0;
        int p = 0;
        int r = 1;
        for (int i = 1; i <= n; i++) {
          q = p;
          p = r;
          r = q + p;
        }
        return r;
    }
  1. x的平方根
 public int  mysqrt(int x) {
        if (x == 0) {
            return 0;
        }
        int ans = (int)Math.exp(0.5 * Math.log(x));
        return (ans + 1) * (ans + 1) <= x ? ans + 1 : ans;
    }
  1. 文本左右对齐
   public List<String> full(String[] words, int maxWidth) {
        int right = 0;
        int n = words.length;
        List<String> ans = new ArrayList<String>();

        while(true) {
            int left = right;
            int numLen = 0;

            while(right < n && numLen + words[right].length() + right - left <= maxWidth   ) {
                numLen = numLen + words[right++].length();
            }

            if (right == n) {
                StringBuilder sb = join(words, left, right, " ");
                sb.append(back(maxWidth - sb.length()));
                ans.add(sb.toString());
                return ans;
            }

            int numWord = right - left;
            int numSpace = maxWidth - numLen;

            if (numWord == 1) {
                StringBuilder sb = new StringBuilder(words[left]);
                sb.append(back(maxWidth - sb.length()));
                ans.add(sb.toString());
                continue;
            }

            int avgSpace = numSpace / (numWord -1);
            int extraSapce = numSpace % (numWord - 1);

            StringBuilder sb =  join(words, left, left + extraSapce + 1, back(avgSpace + 1));
            sb.append(back(avgSpace));
            sb.append(join(words, left + extraSapce + 1, right, back(avgSpace)));
            ans.add(sb.toString());
        }

    }

    public StringBuilder join(String[] words, int left, int right, String step) {
        StringBuilder sb = new StringBuilder(words[left]);
        for(int i = left +1;  i < right; i++ ) {
            sb.append(step);
            sb.append(words[i]);
        }
        return sb;
    }

    public String back(int n) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            sb.append(" ");
        }
        return sb.toString();
    }

  1. 二进制求和
public String  binaryAdd(String s1, String s2) {
        int len = Math.max(s1.length(), s2.length());
        int res = 0;
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < len; i++) {
            res += i < s1.length() ?  (s1.charAt(s1.length() - i - 1) - '0' ) : 0;
            res += i < s2.length() ?  (s2.charAt(s2.length() - i - 1) - '0' ) : 0;
            sb.append( (char)(res % 2 + '0') );
            res = res /2;
        }
        if (res > 0) {
            sb.append('1');
        }
        sb.reverse();

        return sb.toString();
    }

  1. 加一
    public int[] plusOne(int[] nums) {

        int n = nums.length;

        for (int i = n - 1; i >= 0; i--) {
            if (nums[i] != 9) {
                ++nums[i];
                for (int j = i+1; j < n; j++) {
                    nums[j] = 0;
                }
                return nums;
            }
        }
        int [] res = new int[n +1];
        res[0] = 1;
        return res;
    }
  1. 有效数字
  enum State {
        State_Init,
        State_Singl,
        State_Integer,
        State_Point,
        State_Point_with,
        State_Factor,
        State_Exp,
        State_Exp_Sign,
        State_Exp_Number,
        State_End;
    }

    enum CharType {
        Number,
        Point,
        Sign,
        Exp,
        Ilegal;
    }


    public boolean isNumber(String str){
        int len = str.length();
        Map<State, Map<CharType, State>> tranfer = new HashMap<State, Map<CharType, State>>();

        Map<CharType, State> init = new HashMap<CharType, State>(){{
            put(CharType.Number, State.State_Integer);
                    put(CharType.Point, State.State_Point_with);
                    put(CharType.Sign, State.State_Singl);
        }};
        tranfer.put(State.State_Init, init);


        Map<CharType, State> sign = new HashMap<CharType, State>(){{
            put(CharType.Number, State.State_Integer);
                    put(CharType.Point, State.State_Point_with);
        }};
        tranfer.put(State.State_Singl, sign);

        Map<CharType, State> integer = new HashMap<CharType, State>(){{
            put(CharType.Number, State.State_Integer);
            put(CharType.Point, State.State_Point);
            put(CharType.Exp, State.State_Exp);
        }};
        tranfer.put(State.State_Integer, integer);

        Map<CharType, State> point = new HashMap<CharType, State>(){{
            put(CharType.Exp, State.State_Exp);
                    put(CharType.Number, State.State_Factor);
        }};
        tranfer.put(State.State_Point, point);

        Map<CharType, State> pointWith = new HashMap<CharType, State>(){{
            put(CharType.Number, State.State_Factor);
        }};
        tranfer.put(State.State_Point_with, pointWith);


        Map<CharType, State> factor = new HashMap<CharType, State>(){{
            put(CharType.Number, State.State_Factor);
                    put(CharType.Exp, State.State_Exp);
        }};
        tranfer.put(State.State_Factor, factor);

        Map<CharType, State> exp = new HashMap<CharType, State>(){{
            put(CharType.Number, State.State_Exp_Number);
                    put(CharType.Sign, State.State_Exp_Sign);
        }};
        tranfer.put(State.State_Exp, exp);


        Map<CharType, State> expSign = new HashMap<CharType, State>(){{
            put(CharType.Number, State.State_Exp_Number);
        }};
        tranfer.put(State.State_Exp_Sign, expSign);


        Map<CharType, State> expNumber = new HashMap<CharType, State>(){{
            put(CharType.Number, State.State_Exp_Number);
        }};
        tranfer.put(State.State_Exp_Number, expNumber);


        State state = State.State_Init;

        for (int i = 0; i < len; i++) {
            char ch = str.charAt(i);
            CharType charType = toChartype(ch);
            if (!tranfer.get(state).containsKey(charType)) {
                return false;
            }
            state = tranfer.get(state).get(charType);
        }
        return  state ==State.State_Integer || state == State.State_Factor || state == State.State_Exp_Number || state == State.State_Point || state == State.State_End;

    }

    public CharType toChartype(char ch) {
        if (ch >= '0' && ch <= '9'){
            return CharType.Number;
        }
        if (ch == '-' || ch == '+') {
            return CharType.Sign;
        }
        if (ch == '.') {
            return CharType.Point;
        }
        if (ch == 'e' || ch == 'E') {
            return CharType.Exp;
        }
        return CharType.Ilegal;
    }
  1. 最小路径和
    public int  minPathSum(int [][] nums) {
        int n = nums.length;
        int m = nums[0].length;

        int[][] f = new int[n][m];

        f[0][0] = nums[0][0];
        for (int i = 1; i < n; i++) {
            f[i][0] = f[i  -1][0] + nums[i][0];
        }
        for (int j = 1; j < m; j++) {
            f[0][j] = f[0][j -1] + nums[0][j];
        }

        for (int i = 1; i < n; i++) {
            for (int j = 1; j < m; j++) {
                f[i][j] = Math.min(f[i -1][j], f[i][j -1]) + nums[i][j];
            }
        }
        return f[n -1][m -1];
    }

  1. 不同路径II
public int pathSum1(int[][] nums) {
        int n = nums.length;
        int m = nums[0].length;

        int [][] f = new int[n][m];

        for (int i = 0; i < n; i++) {
            if (nums[i][0] != 0) {
                f[i][0] = 0;
                break;
            }
            f[i][0] = 1;
        }
        for (int j = 0; j < m; j++) {
            if (nums[0][j] != 0) {
                f[0][j] = 0;
                break;
            }
            f[0][j] = 1;

        }
        for (int i = 1; i < n; i++) {
            for (int j = 1; j < m; j++) {
                if (nums[i][j] != 1) {
                    f[i][j] = f[i -1][j] + f[i][j -1];
                }
            }
        }
        return f[n-1][m - 1];
    }
  1. 不同路径
  public int pathCnt(int n, int m) {
        int[][] f = new int[n][m];
        
        for (int i = 0; i < n; i++) {
            f[i][0] = 1;
        }

        for (int j = 0; j < m; j++) {
            f[0][j] = 1;
        }

        for (int i = 1; i < n; i++) {
            for (int j = 1; j < m; j++) {
                f[i][j] = f[i - 1][j] + f[i][j -1];
            }
        }
        return f[n -1][m -1];
    }
  1. 旋转链表
public LinkNode rotateRight(LinkNode head, int k) {
    if (head == null || k == 0 ) {
        return head;
    }
    LinkNode tail = head;
    int len = 1;
    while(tail.next != null) {
        len++;
        tail = tail.next;
    }

    if (len == k) {
        return head;
    }

    tail.next = head;

    int add = len  - k % len;

    while (add > 0) {
        add--;
        tail = tail.next;
    }   
    LinkNode res = tail.next;
    tail.next = null;
    return res;
}
  1. 螺旋矩阵II
  public int[][] martix(int n) {
        int maxMaritx = n * n ;
        int currentNum = 1;
        int[][] res = new int[n][n];

        int direIndex = 0;
        int[][] direction = {{0, 1},{1, 0},{0, -1},{-1, 0}};

        int row = 0;
        int col = 0;

        while(currentNum <= maxMaritx) {
            res[row][col] = currentNum;
            currentNum++;

            int nextRow = row + direction[direIndex][0];
            int nextCol = col + direction[direIndex][1];

            if(nextRow < 0 || nextRow >= n || nextCol < 0 || nextCol >= n || res[nextRow][nextCol] != 0) {
                direIndex = (direIndex +1 ) % 4;
            }
            row = row + direction[direIndex][0];
            col = col + direction[direIndex][1];
        }
        return res;
    }

63.最后一个单词的长度

    public int leastSequeLen(String str) {
        int len = str.length();
        int index = len -1;
        int leastLen = 0;

        while(index >=0 && str.charAt(index) == ' ') {
            index--;
        }

        while(index >= 0 && str.charAt(index) != ' ') {
            index--;
            leastLen++;
        }
        return leastLen;
    }
   
  1. 插入区间
   public int[][] merger1 (int[][] nums, int[] newNums) {
        int left = newNums[0];
        int right = newNums[1];

        boolean flag = false;
        List<int[]> merger = new ArrayList<int[]>();

        for (int[] num : nums) {
            if (num[0] > right) {
                if (!flag) {
                    merger.add(new int[]{left, right});
                    flag = true;
                }
                merger.add(num);
            } else if (num[1] < left ) {
                merger.add(num);
            } else {
                left = Math.min(left, num[0]);
                right = Math.max(right, num[1]);
            }
        }
        if (!flag) {
            merger.add(new int[]{left, right});
        }
        int[][] ans = new int[merger.size()][];

        for (int i = 0; i < merger.size(); i++) {
            ans[i] = merger.get(i);
        }
        return ans;
    }
  1. 合并区间
   public int[][] mergerArray(int[][] nums) {
        int len = nums.length;
        if (len == 0) {
            return new int[0][2];
        }
        Arrays.sort(nums, new Comparator<int[]>() {
            public int compare(int[] o1, int[] o2) {
                return o1[0] - o2[0];
            }
        });

        List<int[]> merger = new ArrayList<int[]>();

        for (int[] num : nums) {
            int left = num[0], right = num[1];
            if (merger.size() == 0 || merger.get(merger.size()-1)[1] < left ) {
                merger.add(num);
            } else {
                merger.get(merger.size() - 1)[1] = right;
            }
        }
        return merger.toArray(new int[merger.size()][]);
    }
  1. 跳跃游戏
    public boolean skipGame(int[] nums) {
        int len = nums.length;
        int max  = 0;
        for (int i = 0; i < len; i++) {
            if (max >= i) {
                max = Math.max(max, i + nums[i]);
                if (max >= len -1) {
                    return true;
                }
            }
        }
        return false;
    }
  1. 螺旋矩阵
public List<Integer> luoxuan(int[][] martix) {
        List<Integer> res = new ArrayList<Integer>();

        int rows = martix.length;
        int cols = martix[0].length;

        int left = 0, right = cols -1;
        int top = 0, bottom = rows -1;

        while(left <= right && top <= bottom) {
            for (int i = left; i <=  right; i++) {
                res.add(martix[top][i]);
            }

            for (int i = top + 1; i <= bottom; i++) {
                res.add(martix[i][right]);
            }

            if (left < right && top < bottom) {
                for (int i = right -1 ; i >= left; i-- ) {
                    res.add(martix[bottom][i]);
                }
                for (int i = bottom -1; i > top; i--) {
                    res.add(martix[i][left]);
                }
            }
            left++;
            right--;
            top++;
            bottom--;
        }
        return res;
    }

  1. 最大子数组和
  public int maxChildSeque(int[] nums) {
        int max = nums[0];
        int pre = 0;
        for (int x : nums) {
            pre = Math.max(x, pre + x);
            max = Math.max(max, pre);
        }
        return max;
    }
  1. N皇后II
    public int queues1(int n) {

        int[] queue = new int[n];
        Arrays.fill(queue, -1);
        Set<Integer> col1 = new HashSet<Integer>();
        Set<Integer> da1 = new HashSet<Integer>();
        Set<Integer> da2 = new HashSet<Integer>();
        int i =  back1(queue, n, 0, col1, da1, da2);
        return i;
    }

    public int back1(int[] queue, int n, int row, Set<Integer> col1, Set<Integer> da1, Set<Integer> da2) {

        if (n == row) {

            return 1;
        }
        int count = 0;
        for (int i = 0; i < n ; i++) {

            if (col1.contains(i)) {
                continue;
            }
            int da11 = row - i;
            if (da1.contains(da11)) {
                continue;
            }
            int da22 = row + i;
            if (da2.contains(da22)) {
                continue;
            }
            col1.add(i);
            da1.add(da11);
            da2.add(da22);
            count = count + back1(queue, n , row+1, col1, da1, da2);
            col1.remove(i);
            da1.remove(da11);
            da2.remove(da22);
        }
        return count;
    }
  1. N皇后
   public List<List<String>> queues(int n) {
        List<List<String>> res = new ArrayList<List<String>>();

        int[] queue = new int[n];
        Arrays.fill(queue, -1);
        Set<Integer> col1 = new HashSet<Integer>();
        Set<Integer> da1 = new HashSet<Integer>();
        Set<Integer> da2 = new HashSet<Integer>();
        back(queue, n, 0, col1, da1, da2, res);
        return res;
    }

    public void back(int[] queue, int n, int row, Set<Integer> col1, Set<Integer> da1, Set<Integer> da2, List<List<String>> res  ) {

        if (n == row) {
            List<String> str = board(queue, n);
            res.add(str);
            return;
        }

        for (int i = 0; i < n ; i++) {
            if (col1.contains(i)) {
                continue;
            }
            int da11 = row - i;
            if (da1.contains(da11)) {
                continue;
            }
            int da22 = row + i;
            if (da2.contains(da22)) {
                continue;
            }
            queue[row] = i;
            col1.add(i);
            da1.add(da11);
            da2.add(da22);
            back(queue, n , row+1, col1, da1, da2, res);
            queue[row] = -1;
            col1.remove(i);
            da1.remove(da11);
            da2.remove(da22);
        }
    }

    public List<String> board(int[] queue, int n) {
        List<String> res = new ArrayList<String>();
        for (int i = 0; i < n; i++) {
            char [] chars = new char[n];
            Arrays.fill(chars, '.');
            chars[queue[i]] = 'Q';
            res.add(new String(chars));
        }
        return res;
    }

55.实现pow(x,n)

 public double pow(double x,  int n) {
        long N = n;
        return N >= 0 ? mul(x, N) : 1.0/mul(x,-N);
    }

    public double mul(double x, long n) {
        double ans  = 1.0;

        double double_x = x;

        while(n > 0) {
            if (n % 2 == 1) {
                ans = ans * double_x;
            }
            double_x = double_x * double_x;
            n = n /2;
        }
        return ans;
    }
  1. 字母异位词分组
 public List<List<String>> yiwei(String[] nums) {
        Map<String, List<String>> map = new HashMap<String, List<String>>();
        for (String num : nums) {
            char [] chars = num.toCharArray();
            Arrays.sort(chars);
            String s1 = new String(chars);
            List<String> list = map.get(s1);
            if (list == null) {
                list = new ArrayList<String>();
            }
            list.add(num);
            map.put(s1, list);
        }
        return new ArrayList<List<String>>(map.values());
    }

53.旋转图像

核心: nums[col][n -  row -1] = nums[row][col] 


    public void xuanzhuan(int[][] nums) {
        int n = nums.length;

        for (int row = 0; row < n/2; row++) {
            for (int col = 0; col < (n+1)/2; col++) {
                int temp = nums[row][col];
                nums[row][col] = nums[n - 1 - col][row];
                nums[n - 1 - col][row] = nums[n - row -1][n -1 -col];
                nums[n - row -1][n -1 -col] = nums[col][n - row - 1];
                nums[col][n - row - 1] = temp;
            }
        }
    }
  1. 全排列2
数组有重复元素

   boolean[] bis;

    public List<List<Integer>> pailie2(int[] nums) {
        List<List<Integer>> res  = new ArrayList<List<Integer>>();
        List<Integer> ans = new ArrayList<Integer>();
        bis = new boolean[nums.length];
        Arrays.sort(nums);
        back2(nums, res, ans, 0);
        return res;
    }

    public void back2(int[] nums, List<List<Integer>> res, List<Integer> ans, int n) {
        if (n == nums.length) {
            res.add(new ArrayList<Integer>(ans));
            return;
        }

        for (int i = 0; i < nums.length; i++) {
            if (bis[i] ||  (i > 0 && nums[i] == nums[i -1] && !bis[i-1])   ) {
                continue;
            }
            ans.add(nums[i]);
            bis[i] = true;
            back2(nums, res, ans,  n +1);
            bis[i] = false;
            ans.remove(n);
        }
    }
   
  1. 全排列
输入数组不重复

    public List<List<Integer>> pailie(int [] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        List<Integer> output = new ArrayList<Integer>();

        for (int num : nums) {
            output.add(num);
        }
        int len = nums.length;
        back(len, res, output, 0);
        return res;
    }

    public void back(int len, List<List<Integer>> res, List<Integer> output,  int first) {
        if (first == len) {
            res.add(new ArrayList<Integer>(output));
        }

        for (int i = first; i < len; i++) {
            Collections.swap(output, i, first);
            back(len, res, output, first +1);
            Collections.swap(output, i , first);
        }
    }


    public void printListList(List<List<Integer>> res) {
        for (List<Integer> list : res) {
            for (Integer num : list) {
                System.out.printf(num + ",");
            }
            System.out.println("");
        }

    }
  1. 跳跃游戏Ⅱ
public int skip(int[] nums) {
        int len = nums.length;
        int step = 0;
        int end = 0;
        int maxPosition = 0;

        for (int i = 0; i < len -1; i++) {
            maxPosition = Math.max(maxPosition, i + nums[i]);
            if (i == end) {
                end = maxPosition;
                step++;
            }
        }
        return step;
    }
  1. 字符串相乘
    public String mul(String num1, String num2) {
        if (num1.equals("0") || num2.equals("0") ) {
            return "0";
        }
        String res = "";
        for (int i = num1.length() -1; i >= 0; i-- ) {
            StringBuilder temp = new StringBuilder();

            for (int j = 0; j < num1.length() - i - 1; j++) {
                temp.append("0");
            }
            int carry = 0;
            int n1 =  num1.charAt(i) - '0';
            for (int j = num2.length() -1; j >= 0 || carry != 0; j-- ) {
                int n2 = j < 0 ? 0 : num2.charAt(j) - '0';
                int value = (n1 * n2 + carry) %10;
                temp.append(value);
                carry = (n1 * n2 + carry) /10;
            }
            res =  addString(res, temp.reverse().toString());
        }
        return res.toString();
    }

    public String addString(String num1, String num2) {
        StringBuilder res = new StringBuilder();
        int carry = 0;
        for (int i = num1.length() -1, j = num2.length() -1; i >= 0 || j >= 0 || carry != 0 ; i--, j-- ) {
            int n1 = i < 0 ? 0 : num1.charAt(i) - '0';
            int n2 = j < 0 ? 0 : num2.charAt(j) - '0';
            int sum = (n1 + n2 + carry) % 10;
            res.append(sum);
            carry = (n1 + n2 + carry) /10;
        }
        return res.reverse().toString();
    }
  1. 接雨水
public int yushui(int[] nums) {
    int left = 0;
    int right = nums.length -1;
    int left_max = 0;
    int right_max = 0;
    int ans = 0;
    while(left < right){
        if (nums[left] < nums[right]) {
            if (nums[left] > left_max) {
                left_max = nums[left];
            } else {
                ans = ans + left_max - nums[left];
            }
            left++;
        } else {
            if (nums[right] > right_max) {
                right_max = nums[right];
            } else {
                ans = ans + right_max - nums[right];
            }
            right--;
        }
    }
    return ans;
}
  1. 缺失的第一个正数
public int minValue(int [] nums) {
    int len = nums.length;

    for (int i = 0; i < len; i++) {
        while(nums[i] > 0 && nums[i] <= len && nums[nums[i] - 1] != nums[i]) {
            swapArray(nums, i, nums[i] -1);
        }
    }

    for (int i = 0; i < len; i++) {
        if (nums[i] !=  i + 1 ) {
            return i +1;
        }
    }
    return len +1;
}

public void swapArray(int [] nums, int index, int index1) {
    int temp = nums[index];
    nums[index] = nums[index1];
    nums[index1] = temp; 
}
  1. 组合总数二
   public List<List<Integer>> shulie(int [] nums, int target) {
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        List<Integer> combine = new ArrayList<Integer>();
        Arrays.sort(nums);
        dfs(nums, target, 0, combine, ans);
        return ans;
    }

    public void dfs(int[] nums, int target, int start, List<Integer> combine, List<List<Integer>> ans) {
        if (target < 0) {
            return;
        }

        if(target == 0) {
            ans.add(new ArrayList(combine));
            return;
        }

        for (int i = start; i < nums.length; i++) {
            if (i > start && nums[i] == nums[i -1]) {
                continue;
            }
            combine.add(nums[i]);
            dfs(nums, target - nums[i], i + 1  , combine, ans);
            combine.remove(combine.size() - 1);
        }
    }
  1. 组合总和
 public List<List<Integer>> shulie(int [] nums, int target) {
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        List<Integer> combine = new ArrayList<Integer>();
        dfs(nums, target, 0, combine, ans);
        return ans;
    }

    public void dfs(int[] nums, int target, int start, List<Integer> combine, List<List<Integer>> ans) {
        if (target < 0) {
            return;
        }

        if(target == 0) {
            ans.add(new ArrayList(combine));
            return;
        }

        for (int i = start; i < nums.length; i++) {
            combine.add(nums[i]);
            dfs(nums, target - nums[i], i, combine, ans);
            combine.remove(combine.size() - 1);
        }
    }

44.前观数列

    public String countAndSay(int n) {
        String str = "1";
        for (int i = 2; i <= n; i++) {
            StringBuilder sb = new StringBuilder();
            int pos  = 0;
            int start = 0;
            while(pos < str.length()) {
                while(pos < str.length() && str.charAt(pos) == str.charAt(start)) {
                    pos++;
                }
                sb.append(Integer.toString(pos - start)).append(str.charAt(start));
                start = pos;
            }
            str = sb.toString();
        }
        return str;
    }
  1. 解数独
public class sudu{

    boolean [][] col = new boolean[9][9];
    boolean [][] row = new boolean[9][9];
    boolean [][][] box = new boolean[3][3][9];
    boolean valid = false;
    List<int[]> spaces = new ArrayList<int[]>();


    public void solvesudo(char[][] board) {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                char c = board[i][j];
                if (c == '.') {
                    spaces.add(new int[]{i, j});
                } else {
                    int digt = c - '0' - 1;
                    col[i][digt] = row[j][digt] = box[i][j][digt] = true;
                }
            }
        }
        dfs(board, 0);
    }

    public void dfs(char[][] board, int pos) {
        if (spaces.size() == pos) {
            valid = true;
            return;
        }
        int[] space = spaces.get(pos);
        int i = space[0];
        int j = space[1];
        for (int digt = 0;  digt < 9  && !valid; digt++) {
            col[i][digt] = row[j][digt] = box[i/3][j/3][digt] = true;
            board[i][j] = (char)(digt - '0' + 1);
            dfs(board, pos + 1);
            col[i][digt] = row[j][digt] = box[i/3][j/3][digt] = false;
        }
    }
} 
  1. 有效数独
public boolean judgesudu(char[][] borad) {
    int [][] col = new int [9][9];
    int [][] row = new int[9][9];
    int[][][] box = new int[3][3][9];

    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            char c = borad[i][j];
            if (c != '.') {
                int index = c - '0' -1;
                col[i][index]++;
                row[j][index]++;
                box[i\3][j\3][index]++;
                if (col[i][index] > 1 || row[j][index] > 1 || box[i\3][j\3][index] > 1 ) {
                    return false;
                }
            }
        }
    }
    return true;
}
  1. 搜索插入位置
    public int searchInsert(int[] nums, int target) {
        int l = 0;
        int r = nums.length -1;
        int ans = nums.length;
        while(l <= r) {
            int mid = (l + r ) / 2;
            if (nums[mid] >= target) {
                r = mid  -1;
                ans = mid;
            } else {
                l = mid +1;
            }
        }
        return ans;
    }
  1. 在排序数组中查找元素的第一个和最后一个位置
    public int[] findIndex(int[] nums, int target) {
        int left = searchIndex(nums, target, true);
        int right = searchIndex(nums, target, false) -1;
        if (left <= right && right < nums.length && nums[left] == target && nums[right] == target) {
            return new int[] {left, right};
        }
        return new int[] {-1, -1};
    }

    public int searchIndex(int[] nums, int target, boolean lower) {
        int len = nums.length;
        int l = 0;
        int r = len -1;
        int ans = 0;
        while(l <= r) {
            int mid = (l + r) / 2;
            if (nums[mid] > target || (lower && nums[mid] >= target ) ) {
                r = mid  - 1;
                ans = mid;
            } else {
                l = mid + 1;
            }
        }
        return ans;
    }

39.搜索旋转排序数组

    public int findTarget(int [] nums, int target) {
        int len = nums.length;
        if (len == 0) {
            return -1;
        }
        if (len ==1) {
            return nums[0] == target ? 0 : -1;
        }
        int l  = 0;
        int r = len -1;
        while(l <= r) {
            int mid = (r + l )/2;
            if (nums[mid] == target) {
                return mid;
            }
            if (nums[0] <= nums[mid]) {
                if (nums[0] <= target && target < nums[mid] ) {
                    r = mid - 1;
                } else {
                    l = mid +1;
                }

            } else {
                if (nums[mid] < target && target <= nums[len -1]  ) {
                    l = mid + 1;
                } else {
                    r = mid -1;
                }
            }
        }
        return -1;
    }

  1. 下一个排列
    public void nextPailie(int[] nums) {
        int len = nums.length;
        int j = len -2;
        while(j >= 0 && nums[j] >= nums[j +1]) {
            j--;
        }
        if (j >= 0) {
            int i = len - 1;
            while(i >= 0 && nums[j] > nums[i] ) {
                i--;
            }
            swap(nums, i, j);
        }
        resver(nums, j +1);
    }

    public void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    public void resver(int[] nums, int start) {
        int left = start;
        int right = nums.length - 1;
        while(left < right) {
            swap(nums, left, right);
            left++;
            right--;
        }
    }
  1. 最长的有效括号
public int maxlong(String str) {
    int len = str.length();
    int [] dp = new int[len];
    int maxAns = 0;
    for (int i = 1 ; i <len; i++ ) {
        if (str.charAt(i) == ')' ) {
            if (str.charAt(i -1 ) == '(') {
                dp[i] =  (i -2 > 0 ? dp[i -2 ] : 0) + 2;
            } else if (i - dp[i -1] - 2 > 0 && str.charAt(i - dp[i-1] -1 )  == '(' ) {
                dp[i] = dp[i -1] +   dp[i - dp[i -1]  -2] + 2;
            }
        }
        maxAns = Math.max(maxAns, dp[i]);
    }
    return maxAns;
}

36.两数相除

public int div(int dividend, int divisor) {
    if (divisor == 0) {
        return 0;
    }
    if (dividend == Integer.MAX_VALUE  ){
        if (divisor == 1) {
            return Integer.MAX_VALUE;
        }
        if (divisor == -1) {
            return Integer.MIN_VALUE;
        }
    }

    if (dividend == Integer.MIN_VALUE ){
        if (divisor == 1) {
            return Integer.MIN_VALUE;
        }
        if (divisor == -1) {
            return Integer.MAX_VALUE;
        }        
    }

    if (divisor == Integer.MAX_VALUE ) {
       if (dividend == Integer.MAX_VALUE) {
           return 1;
       }else if (dividend == Integer.MIN_VALUE) {
           return -1;
       } else {
           return 0;
       }
    }
    
    if (divisor == Integer.MIN_VALUE ) {
       if (dividend == Integer.MAX_VALUE) {
           return -1;
       }else if (dividend == Integer.MIN_VALUE) {
           return 1;
       } else {
           return 0;
       }
    }
    boolean flag = false;
    if (dividend > 0) {
        dividend = -dividend;
        flag = !flag;
    }

    if (divisor > 0) {
        divisor = -divisor;
        flag = !flag;
    }


    List<Integer> ansList = new ArrayList<Integer>();
    ansList.add(divisor);

    int index = 0;
    while(ansList.get(index) > dividend - ansList.get(index) ) {
            ansList.add(ansList.get(index) + ansList.get(index));
            index++;
    }
    int ans = 0;
    for (int i = ansList.size() - 1; i >= 0; i-- ) {
        if (ansList.get(i) >= dividend ) {
            ans += 1 << i;
            dividend -= ansList.get(i);
        }
    }

    return flag ? -ans : ans;

}

35.实现strStr()

暴力法: O(m*n)
public int  strStr(String s,  String pp) {
    int n = s.length();
    int m = pp.length();

    for (int i = 0; i + m < n; i++) {
        boolean flag = true;

        for (int j = 0; j < m; j++) {
            if (s.charAt(i+j) != pp.charAt(j) ) {
                flag = false;
                break;
            }
        }
        if (flag) {
            return i;
        }
    }
        return -1;
}

KMP算法: O(m+n)

public int strStr(String s, String p) {
        int n = s.length();
        int m = p.length();
        if (m == 0) {
            return 0;
        }

        int [] pi = new int[m];

        for (int i= 1, j = 0; i < m ; i++) {
            while(j > 0 && p.charAt(i) != p.charAt(j) ) {
                j = pi[j-1];
            }
            if (p.charAt(i) == p.charAt(j)) {
                j++;
            }
            pi[i] = j;
        }

        for (int i = 0, j = 0; i < n; i++) {
            while(j > 0 && s.charAt(i) != p.charAt(j) ) {
                j =  pi[i];
            }

            if (s.charAt(i) == p.charAt(j)) {
                j++;
            }
            if (j == m) {
                return i - m +1;
            }
        }
        return -1;
}
  1. 移除元素
   public int removeVal(int[] nums, int val) {
        int len = nums.length;
        if (len == 0) {
            return 0;
        }
        int left = 0;
        for(int right = 0; right < len; right++) {
            if (nums[right] != val) {
                nums[left] = nums[right];
                left++;
            }
        }
        return left;
    }
  1. 删除有序数组中的重复项
    public int removeRepeat(int[] nums) {
        int len = nums.length;
        if (len == 0) {
            return 0;
        }
        int slow = 1;
        int fast = 1;
        for (int i = 1; i < len; i++) {
            if (nums[fast] != nums[fast-1]) {
                nums[slow] = nums[fast];
                slow++;
            }
            fast++;

        }
        return slow;
    }
  1. K个一组反转链表
 public LinkNode revserGroup(LinkNode head, int k) {
        if (head == null || head.next == null) {
            return head;
        }
        LinkNode tail = head;
        for (int i = 0 ; i < k; i++ ) {
            if (tail == null) {
                return head;
            }
            tail = tail.next;
        }
        LinkNode newHead =  resver(head, tail);

        head.next =  revserGroup(tail ,k);
        return newHead;
    }

    public LinkNode resver(LinkNode head, LinkNode tail) {

        LinkNode next = null;
        LinkNode pre = null;

        while(head != tail) {
            next = head.next;
            head.next = pre;
            pre = head;
            head = next;
        }
        return pre;
    }

31.两两交换链表中的节点

public LinkNode swap(LinkNode node) {
    if (node == null || node.next == null) {
        return node;
    }
    LinkNode newHead = node.next;
    node.next = swap(node.next.next);
    newHead.next = node;
    return newHead;
}
  1. 合并K个升序链表
    public LinkNode merger(LinkNode l1, LinkNode l2) {
        if (l1 == null) {
            return l2;
        } else if (l2 == null) {
            return l1;
        } else if (l1.value < l2.value) {
            l1.next = merger(l1.next, l2);
            return l1;
        } else {
            l2.next = merger(l1, l2.next);
            return l2;
        }
    }

    public LinkNode merges (LinkNode[] list) {
        LinkNode node = null;
        for (LinkNode node1 : list) {
            node = merger(node, node1);
        }
        return node;
    }
  1. 括号生成
ArrayList[] cache = new ArrayList[100];

public List<String> generate(int n) {
    if (cache[n] != null ) {
        return cache[n];
    }
    ArrayList<String> ans = new ArrayList<String>();

    if (n == 0) {
        ans.add("");
    } else {
        for (int i = 0; i < n; i++) {
            for (String left : generate(i)) {
                for (String right : generate(n - i - 1)) {
                    ans.add('(' + left + ')' + right);
                }
            }
        }
    }
    cache[n] = ans;
    return ans;
}

  1. 合并两个有序链表
 public LinkNode mergeTwo(LinkNode l1, LinkNode l2) {
        if (l1 == null) {
            return l2;
        } else if (l2 == null) {
            return l1;
        } else if (l1.value < l2.value) {
            l1.next = mergeTwo(l1.next, l2);
            return l1;
        } else {
            l2.next = mergeTwo(l1, l2.next);
            return l2;
        }
    }

27.有效的括号

public boolean judgeStr(String s) {
        int len = s.length();
        if (len % 2 == 1) {
            return false;
        }
        Map<Character, Character> map = new HashMap<Character, Character>();
        map.put(')', '(');
        map.put(']', '[');
        map.put('}', '{');

        LinkedList<Character> link  = new LinkedList<Character>();

        for (int i = 0; i < len; i++) {
            char  ch =  s.charAt(i);
            if (map.containsKey(ch)) {
                if (link.isEmpty() || map.get(ch)  !=  link.getLast() ) {
                    return false;
                }
                link.removeLast();
            } else {
                link.add(ch);
            }
        }
        return link.isEmpty();
    }
  1. 删除列表的倒数第N个节点
public LinkNode removeN(LinkNode head, int n) {
    if (head == null || n <= 0) {
        return null;
    }
    int len = getLength(head);
    LinkNode node = new LinkNode();
    node.next = head;
    node.value = 0;

    for (int i = 1; i < lenght - n + 1; i++) {
        node =  node.next;
    }

    node.next =  node.next.next;
    return head;
}

public int getLength(LinkNode head) {
    int length = 0;
    while(head != null) {
        head = head.next;
        length++;
    }
    return length;
}
  1. 电话号码的字母组合
public List<String> get(String s) {
     List<String> res = new ArrayList<String>();
     if (s == null) {
         return res;
     }
     Map<Character, String> map = new HashMap<Character, String>();
     map.put('2', "abc");
     map.put('3', "def");
     map.put('4', "ghi");
     map.put('5', "jkl");
     map.put('6', "mno");
     map.put('7', "pqrs");
     map.put('8', "tuv");
     map.put('9', "wxyz");

     find(s, res, map, 0, new StringBuilder());
     return res;
 }

 public void find(String s, List<String> res, Map map, int index , StringBuilder dig) {
     if (index == s.length()) {
         res.add(dig.toString());
     } else {
         char ch = s.charAt(index);
         String letter = (String)map.get(ch);
         for (int i = 0 ; i < letter.length(); i++ ) {
             char c = letter.charAt(i);
             dig.append(c);
             find(s, res, map, index+1, dig);
             dig.deleteCharAt(index);
         }
     }
 }

24.最接近的三数之和

public int threeNum(int[] nums, int target){
    int n = nums.length;
    Arrays.sort(nums);
    int ans = nums[0] + nums[1] + nums[2];

    for (int i =1; i < n; i++) {
        int start = i + 1;
        int end = n -1;
    
        while(start < end) {
            int sum = nums[i] + nums[start] + nums[end];
            if (Math.abs(sum - target) < Math.abs(ans - target)) {
                ans = sum;
            }
            if (sum < target) {
                start++;
            } else if (sum > target) {
                end--;
            } else {
                return ans;
            }
        }
    }
    return ans;
}

23.三数只和

public List<List<Integer>> threeNum(int[] nums) {
        int n = nums.length;
        Arrays.sort(nums);
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        // a b c
        for (int first = 0; first < n; first++) {

            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }

            int three = n -1;
            for (int scecond = first + 1; scecond < n; scecond++) {
                if (scecond > first +1 &&  nums[scecond] == nums[scecond -1]) {
                    continue;
                }
                while(scecond < three && nums[scecond] + nums[three] + nums[first] != 0 ) {
                    three--;
                }

                if(scecond == three) {
                    break;
                }

                if (nums[first] + nums[scecond] + nums[three] == 0) {
                    List<Integer> res = new ArrayList<Integer>();

                    res.add(nums[first]);
                    res.add(nums[scecond]);
                    res.add(nums[three]);
                    list.add(res);
                }
            }

        }
        return list;
    }
  1. 最长公共前缀
public String maxCommonSub(String[] arrays) {
  if (arrays == null) {
      return "";
  }
 String ans = arrays[0];
 String s1 = arrays[0];
 for (int i = 1; i < arrays.length; i++) {
     int j = 0;
     for (; j < ans.length() && j < arrays[i].length(); j++ ) {
         if (s1.charAt(j) != arrays[i].charAt(j) ) {
             break;
         }
     }
     ans = ans.substring(0, j);
 }
 return ans;

}

21 罗马数字转整数

public int luomaToInt(String s1) {
    Map<Character, Integer> map = new HashMap<Character, Integer>();
    map.put('I', 1);
    map.put('V', 5);
    map.put('X', 10);
    map.put('L', 50);
    map.put('C', 100);
    map.put('D', 500);
    map.put('M', 1000);

    int n =  s1.length();
    int ans = 0;
    for (int i = 0; i < n; i++) {
        int value = map.get(s1.charAt(i));
        if (i < n-1 && value < map.get(s1.charAt(i+1)) ) {
            ans =  ans - value;
        } else {
            ans = ans + value;
        }
    }
    return ans;
}
  1. 整数转罗马数字
publuic String luoma(int num) {
    int[] arrays = {1000, 900, 500, 400, 100, 90, 50, 40, 10 ,9, 5, 4, 1};
    String[] array1 =  {   "M",  "CM",  "D",   "CD",   "C", "XC",  "L", "XL",  "X", "IX", "V", "IV", "I"};
    StringBuilder sb  = new StringBuilder();
    for (int i = 0; i < arrays.length; i++ ) {
        int value = arrays[i];
        while(num >= value ) {
            num = num - value;
            sb.append(array1[i]);
        }
        if (num == 0) {
            break;
        }
    }
    return sb.toString();
}

19.盛水最多的容器

public int maxArea(int[] arrays) {
    if (arrays == null) {
        return 0;
    }
    int l = 0;
    int r = arrays.length -1;
    int ans = 0;
    while(l < r) {
        int area =  Math.min(arrays[l], arrays[r]) * (r-l);
        ans =  Math.max(ans, area);
        if (arrays[l] <= arrays[r]) {
            l++;
        } else {
            r--;
        }
    }
    return ans;
}

18.正则表达式

public boolean isMatch(String s, String p){
    int m = s.length();
    int n = p.length();

    boolean[][] dp = new boolean [m+1][n+1];
    dp[0][0] = true;
    for (int i = 0; i<= m; ++i) {
        for (int j =1; j <=n; ++j) {
             if (p.charAt(j-1) == '*') {
                 dp[i][j] = dp[i][j-2];
                 if (match(s,p,i,j-1)) {
                    dp[i][j] = dp[i][j] || dp[i-1][j];
                }
             } else {
                 if (match(s,p, i, j)) {
                    dp[i][j] = dp[i-1][j-1];
                 }
             }
        }
    } 
    return dp[m][n];
}

public boolean match(String s, String p, int i, int j) {
        if (i ==0) {
            return false;
        }
        if (p.charAt(j- 1) == '.') {
            return true;
        }
        return s.charAt(i-1) == p.charAt(j-1);
}
  1. 回文数
public boolean judege(int x) {
    if (x < 0  || (x % 10 == 0 && x != 0)) {
        return false;
    }
    int num = 0;
    while(x > num) {
        num = num * 10 + x % 10;
        x = x /10;
    }
    return x == num || num/10 == x;
}

16.字符串转整数

public int myAtoi(String s1) {
        if (s1 == null || s1.length() == 0) {
            return 0;
        }
        int index = 0;
        char[] chars = s1.toCharArray();
        int len = s1.length();

        while(index < len && chars[index] == ' ') {
                index++;
        }
        if (index >= len) {
            return 0;
        }
        int sign = 1;
        if (chars[index] == '+') {
            index++;
        } else if (chars[index] == '-') {
            sign = -1;
            index++;
        }
        int res = 0;
        while(index < len) {
            char ch = chars[index];
            if (ch < '0' || ch > '9'  ) {
                break;
            }
            int tmp = ch - '0';
            if (res > Integer.MAX_VALUE/10 || (res == Integer.MAX_VALUE / 10 &&  ch > Integer.MAX_VALUE % 10 ) ) {
                return 0;
            }
            if (res < Integer.MIN_VALUE/10 || (res == Integer.MIN_VALUE / 10 &&  ch > -(Integer.MIN_VALUE % 10) ) ) {
                return 0;
            }
            res = res * 10 + sign * tmp;
            index++;
        }
        return res;
    }

15 整数反转

public int reserver(int x) {
    int res = 0;
    while(x != 0) {
        int temp = x % 10;
        if (res > Integer.MAX_VALUE /10 || res < Integer.MIN_VALUE /10) {
            return 0;
        }
        res = res * 10 + temp;
        x = x/10;
    }
    return res;
}

14 z型变换

public String  reserver(String s1, int rowNum) {
    if (rowNum < 2) {
        return s1;
    }
    StringBuilder[] sbs = new StringBuilder[rowNum];
    int flag = -1;
    int i = 0;
    char[] chars = s1.toCharArray();
    for (char ch: chars) {
        sbs[i].append(ch);
        if (i ==0 || i+1 == rowNum ) {
            flag = -flag;
        }
        i = i + flag;
    }
    StringBuilder sb  = new StringBuilder();
    for(StringBuilder s : sbs ) {
        sb.append(s);
    }
    return sb.toString();
}

13 最长回文子串

public  String  lonngestPalindrome(String s1) {
    int len = s1.length();
    if (len < 2 ) {
        return s1;
    }
    char[] chars = s1.toCharAray();
    boolean [][] dp = new boolean[len][len]; 
    for (int i = 0; i < len; i++) {
        dp[i][i] = true;
    }
    int begin = 1;
    int maxLen = 0;
    for (int L = 2; L <= len; L++ ) {
        for (int i = 0; i < len; i++) {
            int j = L + i - 1;
            if (j >= len) {
                break;
            }
            if (chars[i] == chars[j]) {
                if (j-i < 3) {
                    dp[i][j] = true;
                } else {
                    dp[i][j] = dp[i+ 1] [j -1];
                }
            } else {
                dp[i][j] = false;
            }
            if (dp[i][j] & j - i +1 > maxLen ) {
                begin = i;
                maxLen = j -i +1;
            }
        }
        return  s1.subString(begin, begin+maxLen);
    }
}
  1. 输出两个有序数组的中位数
 public  double mid(int[] num1, int start1, int end1, int[] num2, int start2, int end2, int k) {
        int len1 = end1 - start1 +1;
        int len2 = end2 - start2 +1;

        if (len1 == 0) {
            return num2[start2 + k -1 ];
        } else if(len2 == 0) {
            return num1[start1 + k -1];
        }

        if (k == 1) {
            return Math.min(num1[start1], num2[start2]);
        }

        int i = start1 + Math.min(len1, k/2) - 1;
        int j = start2 + Math.min(len2, k/2) -1;

        if (num1[i] < num2[j]) {
            return mid(num1, i +1 , end1, num2, start2, end2, k - (i - start1  +1) );
        } else {
            return mid(num1, start1, end1, num2, j +1 , end2, k - (j - start1  +1) );
        }

    }


    public double find(int[] num1, int[] num2) {
        int len1 = num1.length;
        int len2 = num2.length;

        return   (mid(num1, 0 , len1 -1, num2, 0, len2 -1,  (len1+ len2 +1)/2 )
                +
                mid(num1, 0 , len1 -1, num2, 0, len2 -1,  (len1+ len2 +2)/2 )
        ) * 0.5;

    }
  1. 求无序数组的中位数
public int mid(int[] arrays, int length, int k) {
    if (arrays == null) {
        return 0;
    }
    int smallCnt = 0;
    int equalCnt = 0;
    int bigCnt = 0;
    int[] smallArrays = new int[length];
    int[] equalArrays = new int[length];
    int[] bigArrays = new int[length];

    int base = arrays[0];

    for (int i = 0; i < length; i++) {
        if (base > arrays[i]) {
            smallArrays[smallCnt] = arrays[i];
            smallCnt++;
        } else if (base == arrays[i]) {
            equalArrays[equalCnt] = arrays[i];
            equalCnt++;
        } else {
            bigArrays[bigCnt] = arrays[i];
            bigCnt++;
        }
    }

    if (k <= smallCnt) {
        return mid(smallArrays, smallCnt, k);
    } else if (k > smallCnt + equalCnt) {
        return mid(bigArrays, bigCnt, k - smallCnt - equalCnt);
    } else {
        return base;
    }
}

public int mid(int [] arrays) {
    int midValue = 0;

    if (arrays.length % 2 == 0 ) {
        int count1 = mid(arrays, arrays.length, arrays.length/2);
        int count2 = mid(arrays, arrays.length, arrays.length/2 + 1);
        midValue = (count1 + count2) / 2;
    } else {
        midValue = mid(arrays, arrays.length, (arrays.length +1)/2);
    }
    return midValue;
}
  1. 无重复字符的最长子串
滑动窗口

public int maxSubStr(String s1) {
    if (s1 == null) {
        return 0;
    }
    HashSet<Charraset> set = new  HashSet();

    int left = 0;
    int right = 0;
    int max = 0;
    for (; right < s1.length(); right++) {
        Charraset ch =  s1.charAt(right);
        while(set.contains(ch)) {
            set.remove(s1.charAt(left));
            left++;
        }
        set.add(ch);
        max = Math.max(max, right -left +1);
    }
    return max;

}

9.两数相加

public LinkNode add(LinkNode l1, LinkNode l2) {
    
    LinkNode head = null;
    LinkNode tail = null;
    int carry = 0;

    while(l1 != null || l2 != null) {
        int l1 = l1 != null ? l1.value : 0;
        int l2 = l2 != null ? l2.value : 0;

        int sum = l1 + l2 + carry;

        if (head == null) {
            head = new LinkNode(sum % 10);
            tail = head;
        } else {
            tail.next = new LinkNode(sum % 10);
            tail = tail.next; 
        }

        if (l1 != null) {
            l1 = l1.next;
        }
        if (l2 != null) {
            l2 = l2.next;
        }
        carry = sum / 10;
    }

    if (carry > 0) {
        tail.next = new LinkNode(carry);
    }
    return head;

}

8.两数之和

public int[] find(int[] arrays, int target) {
    if (arrays == null) {
        return null;
    }
    Map<Integer, Integer> map = new HashMap();
    for (int i = 0; i < arrays.length; i++) {
        if (map.containkey(target - arrays[i])) {
            return new int[]{map.get(target - arrays[i]), i };
        }
        map.put(arrays[i], i);
    }
    return new int[0];

}

7.从尾到头输出链表

public void print(LinkNode node) {
    if (node == null) {
        return;
    }
    if (node.next != null) {
        print(node.next);
    }
    System.out.print(node.value)
}

6.输入二维数组,找出是否指定值存在


public boolean find(int[][] arrays, int rows, int cols, int target) {
    if (arrays == null || rows < 0 || cols < 0) {
    }
    int row = 0;
    int col = cols -1;

    while (row < rows && col > 0 ) {
        if (arrays[row][col] == target) {
            return true;
        } else if(arrays[row][col] > target) {
            col--;
        }  else {
            row ++;
        }
    }
    return false;

}

5.判断数组是否是树的后序遍历

public boolean judge(int[] arrays, int start, int end) {
    if (arrays == null || start  < 0 || end < 0) {
        return false;
    }
    int root = arrays[end];
    int i = 0;
    for (; i < end; i++) {
        if (arrays[i] > root ){
            break;
        }
    }
    int j = i;
    for (; j < end; j++) {
        if (arrays[j] < root ) {
            return false;
        }
    }

    boolean left = true;
    if (i > start) {
        left = judge(arrays, start, i);
    }
    boolean right = true;
    if (i < end) {
        right = judge(arrays, i, end -1);
    }
    return left && right;
}

4.输出二叉树的后序遍历

public void print(TreeNode root) {
    if (root == null) {
        return;
    }
    if (root != null) {
        print(root.left);
        print(root.right);
    }
    system.out.print(root.value);
}

3.找出数组中重复的数字

public int find(int[] arrays) {
    if (arrays == null) {
        return -1;
    }
    HashSet<Integer> set = new HashSet();
    for (int i = 0; i < arrays.length; i++) {
        int number = arrays[i];
        if (set.contains(number)) {
            return number;
        }
        set.add(number);
    }
    return -1;
} 

2.快速排序

 public void quickSort(int [] nums, int left ,int right) {
        if (nums == null || left > right) {
            return;
        }
        int base = nums[left];
        int i = left;
        int j = right;
        while (i < j) {
            while(nums[j] > base && i < j) {
                j--;
            }
            while(nums[i] < base && i < j) {
                i++;
            }
            int temp  = nums[j];
            nums[j] = nums[i];
            nums[i] = temp;
        }
        quickSort(nums, left , j -1);
        quickSort(nums, j+1, right);
    }

1.一个整形数组中除了两个数字之外,其他都出现了两次,请找出两个只出现一次的数字

//只有一个不重复的 找出一个重复的
public Integer find(int[] arrays) {
    if (arrays == null) {
        return null;
    }
    int number = arrays[0];
    for (int i = 1; i < arrays.length; i++) {
        number = number ^ arrays[i];
    }
    return number;
}



public int[] find(int[] arrays) {
    Integer[]  result = new Integer[2];
    if (arrays == null) {
        return result;
    } 
    int orx = arrays[0];
    for (int i = 1; i < arrays.length; i++) {
        orx = orx ^ arrays[i];
    }
    int index = findIndex(orx);
    result[0] = 0;
    result[1] = 0;
    for (int num : arrays) {
        if (isBit(num, index)) {
            result[0] = result[0] ^ num;
        } else {
            result[1]  = result[1] ^ num;
        }
    }
}

boolean isBit(int num, int index) {
    return (num >>> index) & 1 == 1;
}


int findIndex(orx) {
    int index = 0;
    while(orx & 1 == 0 && index < 32) {
        index++;
        orx  = orx >>> 1;
    }
    return index;
}