力扣---2020.3.6

面试题57 - II. 和为s的连续正数序列

//滑动窗口
class Solution {
    public int[][] findContinuousSequence(int target) {
        List<int[]> list = new ArrayList<>();

        //里要有一个区间的概念,这里的区间是(1, 2, 3, ..., target - 1)
        //套滑动窗口模板,l是窗口左边界,r是窗口右边界,窗口中的值一定是连续值。
        //当窗口中数字和小于target时,r右移; 大于target时,l右移; 等于target时就获得了一个解
        for (int l = 1, r = 1, sum = 0; r < target; r++) {
            sum += r;
            while (sum > target) {
                sum -= l++;
            }
            if (sum == target) {
                int[] temp = new int[r - l + 1];
                for (int i = 0; i < temp.length; i++) {
                    temp[i] = l + i;
                }
                list.add(temp);
            }
        }

        int[][] res = new int[list.size()][];
        for (int i = 0; i < res.length; i++) {
            res[i] = list.get(i);
        }
        return res;
    }
}
class Solution {
    public int[][] findContinuousSequence(int target) {
        ArrayList<int[]> res = new ArrayList<>();
        for(int i = 1;i<=target/2;i++){
            int sum = 0;
            int j = i;
            while(sum<target){
                sum += j;
                j++;
            }
            if(sum == target){
                int[] sol = new int[j-i];
                for(int k = 0;k<j-i;k++){
                    sol[k] = k+i;
                }
                res.add(sol);
            }
        }
        return res.toArray(new int[res.size()][]);
    }
}
//大佬写得,没看懂
class Solution {
    public int[][] findContinuousSequence(int target) {
        
        List<int[]> result = new ArrayList<>();
        int i = 1;

        while(target>0)
        {
            target -= i++;
            if(target>0 && target%i == 0)
            {
                int[] array = new int[i];
                for(int k = target/i, j = 0; k < target/i+i; k++,j++)
                {
                    array[j] = k;
                }
                result.add(array);
            }
        }
        Collections.reverse(result);
        return result.toArray(new int[0][]);       
    }
}

105. 从前序与中序遍历序列构造二叉树

class Solution {
  int pre_idx = 0;
  int[] preorder;
  int[] inorder;
  HashMap<Integer, Integer> idx_map = new HashMap<Integer, Integer>();

  public TreeNode helper(int in_left, int in_right) {
    if (in_left == in_right)
      return null;

    int root_val = preorder[pre_idx];
    TreeNode root = new TreeNode(root_val);
    int index = idx_map.get(root_val);
    pre_idx++;
    root.left = helper(in_left, index);
    root.right = helper(index + 1, in_right);
    return root;
  }

  public TreeNode buildTree(int[] preorder, int[] inorder) {
    this.preorder = preorder;
    this.inorder = inorder;

    int idx = 0;
    for (Integer val : inorder)
      idx_map.put(val, idx++);
    return helper(0, inorder.length);
  }
}
Arrays.copyOfRange(T[ ] original,int from,int to):
将一个原始的数组original,从下标from开始复制,复制到上标to,生成一个新的数组
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length==0) return null;
        //前序第一个元素是根节点
        TreeNode res = new TreeNode(preorder[0]);
        int idx = 0;
        //找到根节点在中序遍历中的下标
        while(preorder[0]!=inorder[idx]) idx++;
        //Arrays.copyOfRange(preorder,1,idx+1),因为前序第一个是根节点,所以从第二个也就是
        //下标为1开始复制。因为含头不含尾,所以最后到idx+1
        //而中序则左右子树在跟节点两点,也就是0-idx-1个都是左子树的,所以这里直接0-idx
        res.left = buildTree(Arrays.copyOfRange(preorder,1,idx+1),Arrays.copyOfRange(inorder,0,idx));
        res.right = buildTree(Arrays.copyOfRange(preorder,idx+1,preorder.length),Arrays.copyOfRange(inorder,idx+1,inorder.length));
        return res;

    }
}

347. 前 K 个高频元素

/*
getOrDefault(Object, V)
这个方法同样检查 Map 中的 Key,如果发现 Key 不存在或者对应的值是 null,则返回第二个参数即默认值。要注意,这个默认值不会放入 Map。
*/
class Solution {
  public List<Integer> topKFrequent(int[] nums, int k) {
    HashMap<Integer, Integer> count = new HashMap();
    for (int n: nums) {
      count.put(n, count.getOrDefault(n, 0) + 1);
    }
    //lambda函数
    PriorityQueue<Integer> heap =
            new PriorityQueue<Integer>((n1, n2) -> count.get(n1) - count.get(n2));

    for (int n: count.keySet()) {
      heap.add(n);
      if (heap.size() > k)
        heap.poll();
    }

    List<Integer> top_k = new LinkedList();
    while (!heap.isEmpty())
      top_k.add(heap.poll());
    Collections.reverse(top_k);
    return top_k;
  }
}
//桶排序
class Solution {
    public List<Integer> topKFrequent2(int[] nums, int k) {
        if (nums == null || nums.length == 0 || k == 0)
            return new ArrayList<>();
        LinkedList<Integer>[] fre = new LinkedList[nums.length + 1];
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }
        for (Integer key : map.keySet()) {
            int value = map.get(key);
            if (fre[value] == null) {
                fre[value] = new LinkedList<>();
            }
            fre[value].add(key);
        }
        List<Integer> res = new ArrayList<>();
        //倒序遍历频率数组,这样可以获取频率从高到低的数字
        for (int i = fre.length - 1; i >= 0 && res.size() < k; i--) {
            LinkedList<Integer> list = fre[i];
            //如果当前频率没有数字,跳过
            if (list == null) {
                continue;
            }
            //相同频率的数字可能有多个,这个只取k个就行,注意顺序是从左往右取
            while (res.size() < k && !list.isEmpty()) {
                res.add(list.removeFirst());
            }
        }
        return res;
    }
}

你知道的越多,你不知道的越多。
有道无术,术尚可求,有术无道,止于术。
如有其它问题,欢迎大家留言,我们一起讨论,一起学习,一起进步

你可能感兴趣的:(数据结构与算法)