剑指offer刷题(1)

这里写目录标题

  • [1. 数组排列](#1. 数组排列)
  • [2. 找出数组中重复的数字](#2. 找出数组中重复的数字)

1. 数组排列

输入一组数字(可能包含重复数字),输出其所有的排列方式。

数据范围

输入数组长度 [0,6]。

数组元素取值范围 [1,10]。

java 复制代码
输入:[1,2,3]
输出:
      [
        [1,2,3],
        [1,3,2],
        [2,1,3],
        [2,3,1],
        [3,1,2],
        [3,2,1]
      ]

解法一

先对数组进行排序,使得可重复的元素相邻,便于后续跳过重复的递归。之后每层递归从未选过的元素中选出一个元素作为第i个数,采用一个bool数组记录哪些元素已经访问过。由于有重复元素存在,在同一层的递归中,同样大小的元素选了就不能再选第二遍了。因此,前一个与自己相同的元素并且被标注过没被访问过,则说明前一个元素已经遍历过了(因为数组排序过,从小到大遍历),后面恢复自己之前的状态了(回溯),因此当前元素不能作为本层元素。如果前一个元素与自己相同,但是显示已经访问过了,说明前一个元素是用在前面某层递归中了,不属于当前层,于是当前元素可以使用。

java 复制代码
class Solution {
    boolean[] visited; 
    
    public List<List<Integer>> permutation(int[] nums) {
        visited = new boolean[nums.length];
        Arrays.sort(nums);
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        arrange(nums,result,0,list);
        return result;
    }
    public void arrange(int[] nums, List<List<Integer>> result, int first, List<Integer> list){
        if(first == nums.length){
            result.add(new ArrayList<Integer>(list));
            return;
        }
        for(int i = 0; i < nums.length; i++){
            if(visited[i] || (i > 0 && nums[i] == nums[i-1] && !visited[i-1])) continue;
            list.add(nums[i]);
            visited[i] = true;
            arrange(nums,result,first+1,list);
            visited[i] = false;
            list.remove(first);
        }
    }
}

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

给定一个长度为 n

的整数数组 nums,数组中所有的数字都在 0∼n−1

的范围内。

数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。

请找出数组中任意一个重复的数字。

注意:如果某些数字不在 0∼n−1

的范围内,或数组中不包含重复数字,则返回 -1;

数据范围

0≤n≤1000

样例

给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。

返回 2 或 3。

解法一

本题可以直接用桶排序,将第一个计数大于1的索引返回即可。但是本题有许多细节需要考虑,例如元素可能大于数组长度n,元素中可能有负数,需要额外考虑。

java 复制代码
class Solution {
    public int duplicateInArray(int[] nums) {
        int n = nums.length;
        int[] bucket = new int[nums.length + 1];
        int flag = 0;
        for(int num : nums){
            if(num < 0 || num >= n ) {
                return -1;
            }
        }
        for(int num : nums){
            bucket[num]++;
            if(bucket[num] > 1) return num;
        }
        return -1;
    }
}

解法二

用hashmap记录出现频次:

java 复制代码
class Solution {
    public int duplicateInArray(int[] nums) {
        int n = nums.length;
        int result = -1;
        HashMap<Integer,Integer> map = new HashMap<>();
        int flag = 0;
        for(int num : nums){
            if(num < 0 || num >= n ) {
                return -1;
            }
            if(map.containsKey(num)){
                result = num;
            }else{
                map.put(num,1);
            }
        }
        return result;
    }
}
相关推荐
墨尘笔尖1 小时前
最大最小值降采样算法的优化
c++·算法
自我意识的多元宇宙3 小时前
二叉树的遍历和线索二叉树--二叉树的遍历
数据结构
qq_5024289903 小时前
清华大学与微软亚洲研究院出品:Kronos 本地部署教程
数据结构·python·金融量化·kronos开源模型
white-persist4 小时前
【vulhub shiro 漏洞复现】vulhub shiro CVE-2016-4437 Shiro反序列化漏洞复现详细分析解释
运维·服务器·网络·python·算法·安全·web安全
FL16238631294 小时前
基于C#winform部署软前景分割DAViD算法的onnx模型实现前景分割
开发语言·算法·c#
baizhigangqw5 小时前
启发式算法WebApp实验室:从搜索策略到群体智能的能力进阶
算法·启发式算法·web app
C雨后彩虹5 小时前
最多等和不相交连续子序列
java·数据结构·算法·华为·面试
cpp_25016 小时前
P2347 [NOIP 1996 提高组] 砝码称重
数据结构·c++·算法·题解·洛谷·noip·背包dp
Hugh-Yu-1301236 小时前
二元一次方程组求解器c++代码
开发语言·c++·算法
编程大师哥6 小时前
C++类和对象
开发语言·c++·算法