查看: 2575| 回复: 5
跳转到指定楼层
上一主题 下一主题
收起左侧

[Leetcode] Leetcode 315 Count of Smaller Numbers After Self 离散化

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
这一题可以用Binary Indexed Tree或者Segment Tree做
有两种方法去建树:
1) 算出数组元素最大最小值,根据权值值域建树
2) 将数组元素离散化,值转换成rank,根据rank (数组大小)建树,最优解

但是在2) 中,离散化这一步是这样实现的:
  1. private void discretization(int[] nums) {
  2.         int[] sorted = nums.clone();
  3.         Arrays.sort(sorted);
  4.         for (int i = 0; i < nums.length; i++) {
  5.             nums[i] = Arrays.binarySearch(sorted, nums[i]) + 1;
  6.         }
  7.     }
复制代码


如果nums[i]有duplicate values的情况下,根据documentation:If the array contains multiple elements with the specified value, there is no guarantee which one will be found.
https://docs.oracle.com/javase/7 ... s.html#binarySearch(byte[],%20byte)
那么相同value的nums[i]可能会return不同的rank,这样算出来的count有可能会不对?可是我按照这个方式去离散化,提交是可以通过的,请问有小伙伴可以解释一下么?


以下是第一种和第二种方法的完整代码
1) 最大最小值
  1. class Solution {
  2.     public List<Integer> countSmaller(int[] nums) {
  3.         // write your code here
  4.         List<Integer> list = new LinkedList<Integer>();
  5.         int min = Integer.MAX_VALUE;
  6.         int max = Integer.MIN_VALUE;
  7.         for (int i = 0; i < nums.length; i++) {
  8.             min = Math.min(min, nums[i]);
  9.             max = Math.max(max, nums[i]);
  10.             list.add(0);
  11.         }
  12.         int[] c = new int[max - min + 2];
  13.         for (int i = nums.length - 1; i >= 0; i--) {
  14.             int val = sum(nums[i] - 1 - min, c);
  15.             update(nums[i] - min, 1, c);
  16.             list.set(i, val);
  17.         }
  18.         return list;
  19.     }
  20.     private int lowbit(int x) {
  21.         return x & -x;
  22.     }
  23.     private void update(int index, int val, int[] c) {
  24.         index++;
  25.         for (int i = index; i <= c.length - 1; i += lowbit(i)) {
  26.             c[i] += val;
  27.         }
  28.     }
  29.     private int sum(int index, int[] c) {
  30.         index++;
  31.         int res = 0;
  32.         for (int i = index; i > 0; i -= lowbit(i)) {
  33.             res += c[i];
  34.         }
  35.         return res;
  36.     }
  37. }
复制代码


2) 离散化之后
  1. class Solution {
  2.     public List<Integer> countSmaller(int[] nums) {
  3.         // write your code here
  4.         List<Integer> list = new LinkedList<Integer>();
  5.         for (int i = 0; i < nums.length; i++) {
  6.             list.add(0);
  7.         }
  8.         discretization(nums);
  9.         int[] c = new int[nums.length + 1];
  10.         for (int i = nums.length - 1; i >= 0; i--) {
  11.             int val = sum(nums[i] - 1, c);
  12.             update(nums[i], 1, c);
  13.             list.set(i, val);
  14.         }
  15.         return list;
  16.     }
  17.     private void discretization(int[] nums) {
  18.         int[] sorted = nums.clone();
  19.         Arrays.sort(sorted);
  20.         for (int i = 0; i < nums.length; i++) {
  21.             nums[i] = Arrays.binarySearch(sorted, nums[i]) + 1;
  22.         }
  23.     }
  24.     private int lowbit(int x) {
  25.         return x & -x;
  26.     }
  27.     private void update(int index, int val, int[] c) {
  28.         index++;
  29.         for (int i = index; i <= c.length - 1; i += lowbit(i)) {
  30.             c[i] += val;
  31.         }
  32.     }
  33.     private int sum(int index, int[] c) {
  34.         index++;
  35.         int res = 0;
  36.         for (int i = index; i > 0; i -= lowbit(i)) {
  37.             res += c[i];
  38.         }
  39.         return res;
  40.     }
  41. }
复制代码



上一篇:想问一下东湾有没有小伙伴想一起刷题的呀
下一篇:692. Top K Frequent Words有点不太懂
全局:
找到值不一定主要是针对首尾说的. 因为源代码里面写只要nums[m] == target 就返回了

这个里面首尾固定, 找出来是一样的.

补充内容 (2018-7-11 05:28):
举个极端点的例子, [10,1,1,1,1,1,1,1,1,1] 这样你nums[i] 会变成[10, 5,5,5,5,5,5,5,5,5] 但是这个rank是不影响你fenwick树里面找frequency, 因为比5小的rank是0个.
回复

使用道具 举报

🔗
 楼主| jocelyna 2018-7-11 06:46:25 | 只看该作者
全局:
肥宅快乐水 发表于 2018-7-11 05:19
找到值不一定主要是针对首尾说的. 因为源代码里面写只要nums[m] == target 就返回了

这个里面首尾固定,  ...

[10,1,1,1,1,1,1,1,1,1] 有可能会变成[10,1,2,3,4,5,6,7,8,9],因为只要找到1就返回它的index,然后加一作为rank,而这里有多个1,无法确定返回的是哪一个呀?
回复

使用道具 举报

全局:
jocelyna 发表于 2018-7-11 06:46
[10,1,1,1,1,1,1,1,1,1] 有可能会变成[10,1,2,3,4,5,6,7,8,9],因为只要找到1就返回它的index ...

可是真的不会。

你看binarySearch 代码呗。。你说会不会变成【10,1,2,3,4,5,6,7,8,9】

```
    public static int binarySearch(int[] a, int key) {
        return binarySearch0(a, 0, a.length, key);
    }

    // Like public version, but without range checks.
    private static int binarySearch0(int[] a, int fromIndex, int toIndex,
                                     int key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            int midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }
```
回复

使用道具 举报

🔗
 楼主| jocelyna 2018-7-11 11:42:38 | 只看该作者
全局:
肥宅快乐水 发表于 2018-7-11 10:47
可是真的不会。

你看binarySearch 代码呗。。你说会不会变成【10,1,2,3,4,5,6,7,8,9】

嗯嗯,确实是的,那就是首尾的index确定的情况下,return回来的index应该是一样的,即使是有重复元素
回复

使用道具 举报

全局:
jocelyna 发表于 2018-7-11 11:42
嗯嗯,确实是的,那就是首尾的index确定的情况下,return回来的index应该是一样的,即使是有重复元素

我回头又想了一下, 这个题我还是建议用merge sort做。
- 方便, - 好写, -容易变形

bit这个方法我想了一下,似乎应用不到别的题上面, 而且需要preprocess,也不是说不好,单纯觉得应用很窄。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表