c#递归函数以循环为错误的顺序?

发布于 2025-01-28 05:06:08 字数 3427 浏览 2 评论 0原文

上下文

我试图编写一种算法来解决以下问题:

给定数字的集合,数字,可能包含重复项,以任何顺序返回所有可能的唯一排列。

我对算法的想法源于您如何解释k-stet的排列数量等于k!:我将第一个元素放在新数组的所有K位置中,对于每个位置,我都将下一个元素放在所有位置可用的剩余位置等,直到最后一个元素。我递归地执行此操作,然后将此递归函数传递给一个字典,以记住下一个元素可用的位置。因为原始数组中可能有重复的元素,所以我使用集合来添加我在算法中提出的排列,并确保它们在集合中是唯一的。放置所有元素后,添加排列。 为止

public class Solution {
    public HashSet<int[]> permutations = new HashSet<int[]>();
    
    public IList<IList<int>> PermuteUnique(int[] nums) {
        int[] permutation = new int[nums.Length];
        Dictionary<int, bool> posTaken = new Dictionary<int, bool>();
        for (int i = 0; i < nums.Length; i++) {
            posTaken.Add(i, false);
        }
        f(nums, 0, permutation, posTaken);
        return new List<IList<int>>(permutations);
    }
    
    private void f(int[] nums, int index, int[] permutation, Dictionary<int, bool> posTaken) {
        Console.WriteLine("index " + index);
        if (index == nums.Length) {
            Console.WriteLine("hey");
            permutations.Add(permutation);
            return;
        }
        for (int i = 0; i < nums.Length; i++){
            if (!posTaken[i]) {
                Console.WriteLine("i " + i);
                Dictionary<int, bool> posTakenCopy = new Dictionary<int, bool>(posTaken);
                int[] permutationCopy = new int[nums.Length];
                permutation.CopyTo(permutationCopy, 0);
                permutationCopy[i] = nums[index];
                Console.WriteLine(string.Join(", ", posTakenCopy.Select(a => $"{a.Key}: {a.Value}")));
                Console.WriteLine("[{0}]", string.Join(", ", permutationCopy));
                posTakenCopy[i] = true;
                f(nums, index++, permutationCopy, posTakenCopy);
            }
        }
    }
}

到现在 真的不明白。

问题

据称所有有效输入都会出现 。下面的输出对应于此输入:[1,2,3]。

运行时错误

首先我会收到以下错误:

未经治疗的例外。 system.indexoutofrangeException:索引不在数组的范围内。 第15行:solution.f(int32 [] nums,int32 index,int32 []置换,词典postaken中的字典postaken)。 ,词典 2 postaken)在解决方案中 第10行:solution.permuteunique(int32 [] nums) 第33行:驱动程序驱动程序 .cs

我打印所有用作此代码中阵列的索引,并且打印的值是始终不如阵列的长度!我肯定忽略了一些东西。

令人惊讶的控制台输出

这是打印到控制台的输出,并具有nums = [1,2,3]。

index 0
i 0
0: False, 1: False, 2: False
[1, 0, 0]
index 0
i 1
0: True, 1: False, 2: False
[1, 1, 0]
index 0
i 2
0: True, 1: True, 2: False
[1, 1, 1]
index 0
i 2
0: True, 1: False, 2: False
[1, 0, 2]
index 1
i 1
0: True, 1: False, 2: True
[1, 2, 2]
index 1
i 1
0: False, 1: False, 2: False
[0, 2, 0]
index 1
i 0
0: False, 1: True, 2: False
[2, 2, 0]
index 1
i 2
0: True, 1: True, 2: False
[2, 2, 2]
index 1
i 2
0: False, 1: True, 2: False
[0, 2, 3]
index 2
i 0
0: False, 1: True, 2: True
[3, 2, 3]
index 2
i 2
0: False, 1: False, 2: False
[0, 0, 3]
index 2
i 0
0: False, 1: False, 2: True
[3, 0, 3]
index 2
i 1
0: True, 1: False, 2: True
[3, 3, 3]
index 2
i 1

第三个字典输出对我来说没有任何意义。这里的“索引”表示元素在原始数组中的位置,我们在所有位置上移动以构建我们的下一个排列。放置它后,我们在词典中记录了下一个元素(作为布尔值)的位置,然后再重复相同的过程。因此,基本上,当索引== 0时,应该只有一个true,所有其他条目应为false。但是词典的第三张打印显示了2个条目false! 在我看来,位置词字典和排列阵列未正确克隆。我在这里做错了什么?

另外,最重要的是,我完全毫无疑问地以此顺序打印索引:0、0,...,1、1,...,2、2,...,2。就像它在做dfs时正在执行BFS一样,如:为什么没有像这样打印的索引:0、1、2、0、1、2等。

Context

I am trying to write an algorithm to solve the following problem:

Given a collection of numbers, nums, that might contain duplicates, return all possible unique permutations in any order.

My idea for an algorithm derives from how you explain the number of arrangements of a k-set is equal to k!: I place the first element in all k position of a new array and for each position I place the next element in all of the available remaining positions etc until the last element. I do this recursively, and I pass to this recursive function a dictionary to memorize which position is available for the next element. Because there can be duplicate elements in the original array, I use a set to add the permutations I come up with in the algorithm and ensure they are unique in the set. The permutations are added when all elements have been placed. So far I've come up with the following algorithm:

public class Solution {
    public HashSet<int[]> permutations = new HashSet<int[]>();
    
    public IList<IList<int>> PermuteUnique(int[] nums) {
        int[] permutation = new int[nums.Length];
        Dictionary<int, bool> posTaken = new Dictionary<int, bool>();
        for (int i = 0; i < nums.Length; i++) {
            posTaken.Add(i, false);
        }
        f(nums, 0, permutation, posTaken);
        return new List<IList<int>>(permutations);
    }
    
    private void f(int[] nums, int index, int[] permutation, Dictionary<int, bool> posTaken) {
        Console.WriteLine("index " + index);
        if (index == nums.Length) {
            Console.WriteLine("hey");
            permutations.Add(permutation);
            return;
        }
        for (int i = 0; i < nums.Length; i++){
            if (!posTaken[i]) {
                Console.WriteLine("i " + i);
                Dictionary<int, bool> posTakenCopy = new Dictionary<int, bool>(posTaken);
                int[] permutationCopy = new int[nums.Length];
                permutation.CopyTo(permutationCopy, 0);
                permutationCopy[i] = nums[index];
                Console.WriteLine(string.Join(", ", posTakenCopy.Select(a => 
quot;{a.Key}: {a.Value}")));
                Console.WriteLine("[{0}]", string.Join(", ", permutationCopy));
                posTakenCopy[i] = true;
                f(nums, index++, permutationCopy, posTakenCopy);
            }
        }
    }
}

This idea may not be the optimal way to solve it but I am still in the draft process just testing stuff, and as I tried to run the code I stumbled upon two issues that I really don't understand.

The problems

Occur for supposedly all valid inputs. The output below corresponds to this input: [1, 2, 3].

A runtime error

First I get the following error:

Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.
Line 15: Solution.f(Int32[] nums, Int32 index, Int32[] permutation, Dictionary2 posTaken) in Solution.cs Line 31: Solution.f(Int32[] nums, Int32 index, Int32[] permutation, Dictionary2 posTaken) in Solution.cs
Line 10: Solution.PermuteUnique(Int32[] nums) in Solution.cs
Line 33: Driver.Main(String[] args) in Driver.cs

I print all variables that are used as indexes for the arrays in this code and the values printed are always inferior to the length of the array! I surely overlooked something.

A surprising console output

This is the output printed to the Console with nums = [1, 2, 3].

index 0
i 0
0: False, 1: False, 2: False
[1, 0, 0]
index 0
i 1
0: True, 1: False, 2: False
[1, 1, 0]
index 0
i 2
0: True, 1: True, 2: False
[1, 1, 1]
index 0
i 2
0: True, 1: False, 2: False
[1, 0, 2]
index 1
i 1
0: True, 1: False, 2: True
[1, 2, 2]
index 1
i 1
0: False, 1: False, 2: False
[0, 2, 0]
index 1
i 0
0: False, 1: True, 2: False
[2, 2, 0]
index 1
i 2
0: True, 1: True, 2: False
[2, 2, 2]
index 1
i 2
0: False, 1: True, 2: False
[0, 2, 3]
index 2
i 0
0: False, 1: True, 2: True
[3, 2, 3]
index 2
i 2
0: False, 1: False, 2: False
[0, 0, 3]
index 2
i 0
0: False, 1: False, 2: True
[3, 0, 3]
index 2
i 1
0: True, 1: False, 2: True
[3, 3, 3]
index 2
i 1

The third dictionary output doesn't make any sense to me. Here "index" denotes the position of the element in the original array that we are moving in all positions to build our next permutation. After we placed it, we record in the dictionary posTaken which positions are available for the next element (as a boolean) before we repeat the same process. So basically, when index == 0, there should only be one True and all other entries should be False. But the third print of the dictionary shows 2 entries False!
It seems to me the position_taken dictionary and the permutation array are not cloned properly. What did I do wrong here?

Additionally and most importantly for me, I am completely clueless as to why the indexes are printed in this order: 0, 0, ..., 1, 1, ..., 2, 2, ..., 2. It looks like it is doing a BFS while it should be doing a DFS, as in: why aren't the indexes printed like this: 0, 1, 2, 0, 1, 2 etc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

怼怹恏 2025-02-04 05:06:08

我的错误:

  1. 索引++:我需要将值复制到另一个变量中以获得适当的行为。

  2. HashSet&lt; int []&gt;的行为不像我想的那样。根据此 /code>和equals()比较两个对象。我需要比较两个数组的内部值以确定它们的平等性,以便先前的实现无法正常工作。我选择使用HashSet&lt; string&gt;,然后将数组转换为字符串以进行足够的比较。


下面的代码虽然不是最佳性能,但可行:

public class Solution {
    public HashSet<string> permutationsSet = new HashSet<string>();
    public List<int[]> permutations = new List<int[]>();
    
    public IList<IList<int>> PermuteUnique(int[] nums) {
        int[] permutation = new int[nums.Length];
        Dictionary<int, bool> posTaken = new Dictionary<int, bool>();
        for (int i = 0; i < nums.Length; i++) {
            posTaken.Add(i, false);
        }
        f(nums, 0, permutation, posTaken);
        return new List<IList<int>>(permutations);
    }
    
    private void f(int[] nums, int index, int[] permutation, Dictionary<int, bool> posTaken) {
        if (index == nums.Length) {
            if(permutationsSet.Add(string.Join("", permutation))) {
                permutations.Add(permutation);
            };
            return;
        }
        for (int i = 0; i < nums.Length; i++){
            if (!posTaken[i]) {
                Dictionary<int, bool> posTakenCopy = new Dictionary<int, bool>(posTaken);
                int[] permutationCopy = new int[nums.Length];
                permutation.CopyTo(permutationCopy, 0);
                permutationCopy[i] = nums[index];
                posTakenCopy[i] = true;
                int indexCopy = index + 1;
                f(nums, indexCopy, permutationCopy, posTakenCopy);
            }
        }
    }
}

My mistakes:

  1. index++: I needed to copy the value into another variable to get the appropriate behaviour.

  2. HashSet<int[]>did not behave like I thought it would. As per this post, HashSet uses GetHashCode() and Equals() to compare two objects. I needed to compare the inner values of both arrays to determine their equality, so the previous implementation could not work. I opted to use HashSet<string>instead, and convert the arrays to strings in order to compare their adequately.

The code below, while not the best performance wise, works:

public class Solution {
    public HashSet<string> permutationsSet = new HashSet<string>();
    public List<int[]> permutations = new List<int[]>();
    
    public IList<IList<int>> PermuteUnique(int[] nums) {
        int[] permutation = new int[nums.Length];
        Dictionary<int, bool> posTaken = new Dictionary<int, bool>();
        for (int i = 0; i < nums.Length; i++) {
            posTaken.Add(i, false);
        }
        f(nums, 0, permutation, posTaken);
        return new List<IList<int>>(permutations);
    }
    
    private void f(int[] nums, int index, int[] permutation, Dictionary<int, bool> posTaken) {
        if (index == nums.Length) {
            if(permutationsSet.Add(string.Join("", permutation))) {
                permutations.Add(permutation);
            };
            return;
        }
        for (int i = 0; i < nums.Length; i++){
            if (!posTaken[i]) {
                Dictionary<int, bool> posTakenCopy = new Dictionary<int, bool>(posTaken);
                int[] permutationCopy = new int[nums.Length];
                permutation.CopyTo(permutationCopy, 0);
                permutationCopy[i] = nums[index];
                posTakenCopy[i] = true;
                int indexCopy = index + 1;
                f(nums, indexCopy, permutationCopy, posTakenCopy);
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文