牛客题目——没有重复项数字的全排列、有重复项数字的全排列


题目1——没有重复项数字的全排列

给出一组数字,返回该数字的所有排列。
要求:空间复杂度为O(n!),时间复杂度O(n!)

示例
输入:[1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

解题思路

最开始就是暴力解法:循环遍历每个数字,然后使用递归将剩下的数字进行全排列,再遍历全排后的结果,与当前的数字合并;当遍历完全部的数字后就能得到最终的全排结果。但是时间复杂度较高。

最合适的方法就是利用递归和回溯。具体做法如下:

  • 先将数组排序,获取字典最小的排列情况;
  • 递归的时候根据当前下表,遍历后续元素,交换二者位置后,进入下一层递归;
  • 处理完一个分支的递归后,将交换的情况再换回来进行回溯,进入其他分支;
  • 当前下标达到数组末尾就是一种排列情况。

递归函数在其定义中直接或间接调用自身的一种方法。它将一个复杂的问题转换为与原问题相似的规模较小的问题来求解。
回溯:指的是在递归的过程中,从某一分支的子问题回到父问题,然后进入父问题的另一子问题分支。

代码实现

import java.util.*;

public class Solution {
    private void swap(ArrayList<Integer> num,int i1,int i2){
        int temp = num.get(i1);
        num.set(i1,num.get(i2));
        num.set(i2,temp);
    }
    public void recursion(ArrayList<ArrayList<Integer>> res,ArrayList<Integer> num,int index){
        //分枝进入结尾,找到一种排列
        //每次添加的时候要new一个新的ArrayList
        if(index == num.size()-1) res.add(new ArrayList(num));
        else{
            for(int i=index;i<num.size();i++){
                //交换两者
                swap(num,i,index);
                //继续往后找
                recursion(res,num,index+1);
                //回溯
                swap(num,i,index);
            }
        }
    }
    public ArrayList<ArrayList<Integer>> permute(int[] num) {
        Arrays.sort(num);
        ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> nums = new ArrayList<Integer>();
        for(int i=0;i<num.length;i++) nums.add(num[i]);
        recursion(res,nums,0);
        return res;
    }
}

题目2——有重复项数字的全排列

给出一组可能包含重复项的数字,返回该数字的所有排列。结果以字典升序排列。
要求:空间复杂度为O(n!),时间复杂度O(n!)

示例
输入:[1,1,2]
输出:[[1,1,2],[1,2,1],[2,1,1]]

解题思路

我们将这个问题看作有n个排列成一行的空格,从左往右依次填入给定的n个数,每个数只能使用一次。
每次填数时,我们肯定不能填已经填过的数,所以可以定义一个标记数组来标记已经填过的数:如果这个数没有被标记过,我们就尝试填入,并将其标记,继续填下一个位置;当回溯的时候,要撤销这个位置填的数以及标记,继续尝试其他没有被标记的数。
但是因为数字存在重复问题,我们需要设置一些条件来保证重复数字只会被填入一次。
条件:mark[i] || i>0 && num[i] == num[i-1] && !mark[i-1]
mark[i]表示下标为i的数字已经填过;
i>0 && num[i] == num[i-1] && !mark[i-1]表示此时的数与上一个相等,并且上一个没有访问过(表示是回溯后的数字),避免了重复

代码实现

import java.util.*;

public class Solution {
    boolean[] mark;
    public void recursion(ArrayList<ArrayList<Integer>> res,LinkedList<Integer> nums,int[] num){
        if(nums.size() == num.length) res.add(new ArrayList<Integer>(nums));
        for(int i=0;i<num.length;i++){
            if(mark[i] || i>0 && num[i] == num[i-1] && !mark[i-1]) 
                continue;
            //添加数字
            nums.add(num[i]);
            mark[i] = true; //设置标记
            recursion(res,nums,num);  //寻找下一个数
            //将上一次全排的结果最后一个数移除掉
            nums.removeLast();
            mark[i] = false; //移除掉的数设置为未访问
        }
    }
    public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
        LinkedList<Integer> nums = new LinkedList<Integer>();
        Arrays.sort(num);
        mark = new boolean[num.length];
        recursion(res,nums,num);
        return res;
    }
### 题目分数预测算法模型 要实现对题目得分情况的预测,可以从以下几个方面入手构建算法模型: #### 数据收集与特征提取 为了建立有效的预测模型,需要先从历史数据中提取有用的特征。这些特征可能包括但不限于用户的解题速度、提交次数、错误率以及每道题目的难度等级[^1]。 对于数据库类题目来说,了解关系模式是否满足一定的范式是非常重要的基础知识点之一。因此,在设计评分机制或者预测系统时,也可以考虑加入关于考生对规范化理论掌握程度的相关指标作为输入变量的一部分。 另外,考虑到不同竞赛平台可能存在差异化的评判标准[^2],所以在准备用于训练的数据集过程中还需要特别留意是否存在因环境设置不当而导致的影响因素,比如某些特定条件下产生的误差可能会间接反映到最终成绩上。 #### 动态规划的应用场景探讨 当涉及到字符串处理类型的编程挑战时,则可运用动态规划方法来解决最短编辑距离之类的问题[^3]。通过计算两个版本之间转换所需的最少操作数,我们不仅能够评估单个参赛者的表现水平,还可以进一步推测整个群体在这方面的平均能力分布状况。 综上所述,一个完整的针对网上各类试题打分趋势分析框架应该综合考量上述提到的各种维度,并采用适当的技术手段加以量化描述。 ```python def predict_score(user_data, problem_features): """ Predicts the score of a user on given problems based on historical data. Args: user_data (dict): Dictionary containing information about past performance. Includes keys like 'speed', 'attempts', etc. problem_features (list): List where each element is another list representing features such as difficulty level and type for one question. Returns: float: Estimated total possible points achievable by this participant under current circumstances. """ estimated_points = sum([calculate_individual_problem_score(u_d, p_f) for u_d,p_f in zip(repeat(user_data),problem_features)]) return round(estimated_points / len(problem_features)*100 ,2) # Example usage demonstrating how function works with dummy values if __name__ == "__main__": sample_user_info={"speed":87,"accuracy_rate":95} questions=[["hard","SQL"],["easy","algorithm"]] print(predict_score(sample_user_info,questions)) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值