分享一道字节面试算法题:统计数字出现的次数

上次面试字节,碰到一个比较有意思的算法题,记录一下,给各位牛友分享。
题意:
给定一个无序数组,长度为n,每个元素都属于范围[1,n]之间,使用时间复杂度O(n)+空间复杂度O(1)的方法,求得每个元素的出现次数。
比如给定数组[1,2,2,3,5,3],最后的结果就是类似于1:1,2:2,3:2,5:1的形式,表示1出现了1次,2出现了2次,3出现了2次,5出现了1次。

解法:
这里限定了时间复杂度,那么只能用边遍历边替换的思路,力扣有移到类似的题 缺失的第一个正数,可以移步查看。

思想就是遍历数组,通过当前位置的数找到对应的下标位置,如果为正数,说明还没有被访问到,需要交换并置为-1,若为负数,需要减去1,若找到的下标不为自己,则把当前位置设为0,之后继续遍历。

步骤:

       1,2,2,3,5,3
第一步 -1,2,2,3,5,3
第二步 -1,-1,2,3,5,3
第三步 -1,-2,0,3,5,3
第四步 -1,-2,-1,0,5,3
第五步 -1,-2,-1,0,-1,3
第六步 -1,-2,-2,0,-1,0

代码:

public class Main {
    public static void main(String[] args) {
        int[][] nums = {
                {1, 1, 2, 2, 3, 5, 2, 3},
                {2, 3, 2, 3, 1},
                {5, 4, 3, 2, 1}
        };
        for (int[] num : nums) {
            System.out.println(Arrays.toString(count(num)));
        }
        // [-2, -3, -2, 0, -1, 0, 0, 0]
        // [-1, -2, -2, 0, 0]
        // [-1, -1, -1, -1, -1]
    }

    public static int[] count(int[] nums) {
        int n = nums.length;
        int i = 0;
        while (i < n) {
            // 只考虑大于0的元素
            while (nums[i] > 0) {
                // 下一个位置
                int next = nums[i] - 1;
                if (nums[next] > 0) {
                    // 交换元素
                    nums[i] = nums[next];
                    nums[next] = -1;
                } else {
                    nums[i] = 0;
                    nums[next]--;
                }
            }
            ++i;
        }
        return nums;
    }
}
#字节面试##面试题目##字节跳动##内推##秋招##Java##校招##笔记#
全部评论
这个代码有问题哦,试试样例5,4,3,2,1
2 回复 分享
发布于 2021-08-30 00:21
这个代码不对吧,比如当输入为{1,5,2,2,3,5,2,3},按这个代码执行的话在第二步就直接更新num[4]=-1,这样在第五步就丢失3这个数了,会少统计一次3
1 回复 分享
发布于 2021-08-29 22:42
不错
点赞 回复 分享
发布于 2021-08-29 21:27
更新了一下解答,感谢大家的纠错,之前想简单了😅
点赞 回复 分享
发布于 2021-08-30 23:38
可以直接用一个int数组嘛?n个元素,每个碰到自加
点赞 回复 分享
发布于 2021-09-18 18:46

相关推荐

11-09 11:01
济南大学 Java
Java抽象带篮子:外卖项目真得美化一下,可以看看我的详细的外卖话术帖子
点赞 评论 收藏
分享
评论
3
12
分享
牛客网
牛客企业服务