【问题标题】:How to find numbers that appear only once in a matrix?如何找到在矩阵中只出现一次的数字?
【发布时间】:2022-01-02 19:31:07
【问题描述】:

我有一个名为 m 的给定矩阵,它的维度是 n x n,它包含整数。我需要将只出现一次的数字复制到一个名为 a 的新数组中。

我认为逻辑是为矩阵中的每个数字设置一个 for 循环,并将其与每个其他数字进行比较,但我不知道如何用代码实际做到这一点。

我只能使用循环(没有地图等),这就是我想出的:

public static void Page111Ex14(int[][] m) {

    int previous = 0, h = 0;
    
    int[] a = new int[m.length*m[0].length];
    
    for (int i = 0; i < m.length; i++) {
        for (int j = 0; j < m[0].length; j++) {
            previous = m[i][j];
            
            if (m[i][j] != previous) {
                a[h] = m[i][j];
                h++;
            }
        }
    }

这可能是不正确的。

【问题讨论】:

  • 如果你有任何起始代码,那会很有帮助
  • 使用Map 并计算每个数字的出现次数。
  • 你可以使用列表还是只使用循环和实际的普通数组?
  • 您还知道其他限制吗?该数字可以是从 Integer.MIN_VALUE 到 Integer.MAX_VALUE 的整个范围内的任何整数吗?解决方案是否需要尽可能高效,或者这不是必需的?可以使用 ArrayList 吗?你可以使用自己的数据结构吗?比如,你能不能定义一个Node类,把它当成链表使用?

标签: java arrays for-loop matrix


【解决方案1】:

再循环一遍,看看有没有重复的。假设你可以使用标签,答案可能有点像这样:

public static int[] getSingleInstanceArrayFromMatrix(int[][] m) {
        int[] a = new int[m.length * m[0].length];

        // Main loop.
        for (int x = 0; x < m.length; x++) {
            for (int y = 0; y < m[0].length; y++) {

                // Gets the current number in the matrix.
                int currentNumber = m[x][y];

                // Boolean to check if the variable appears more than once.
                boolean isSingle = true;

                // Looping again through the array.
                checkLoop:
                for (int i = 0; i < m.length; i++) {
                    for (int j = 0; j < m[0].length; j++) {
                        
                        // Assuring we are not talking about the same number in the same matrix position.
                        if (i != x || j != y) {
                            // If it is equal to our current number, we can update the variable and break.
                            if (m[i][j] == currentNumber) {
                                isSingle = false;
                                break checkLoop;
                            }
                        }
                    }
                }

                if (isSingle) {
                    a[(x * m.length) + y] = currentNumber;
                }
            }
        }

        return a;
    }

不确定它是否最有效,但我认为它会起作用。如果没有 Lists 等的帮助,形成最终的数组有点困难。由于未分配的值将默认为 0,因此如果您查找返回的数组,将不会检测到任何 实际 零(即基于矩阵“假定”存在)。但如果有这样的限制,我想这并不是至关重要的。

【讨论】:

  • 这也会返回很多零,如果输入矩阵中出现此类情况,可能无法与单个零值区分开来。
【解决方案2】:

这是您可以直接使用 HashMap 解决的问题之一,它可以为您完成工作。您遍历 2d 数组,使用 HashMap 存储每个元素及其出现,然后遍历 HashMap 并将所有出现 1 的元素添加到列表中。然后将此列表转换为数组,这是您需要返回的内容。

这具有 O(n*n) 复杂度,其中 n 是方阵 m 的一维。

import java.util.*;
import java.io.*;
    
class GetSingleOccurence
{
    static int[] singleOccurence(int[][] m)
    {
        // work with a list so that we can append to it
        List<Integer> aList = new ArrayList<Integer>();

        HashMap<Integer, Integer> hm = new HashMap<>();

        for (int row = 0; row < m.length; row++) {
            for (int col = 0; col < m[row].length; col++) {
                if (hm.containsKey(m[row][col]))
                    hm.put(m[row][col], 1 + hm.get(m[row][col]));
                else
                    hm.put(m[row][col], 1);
            }
        }

        for (Map.Entry entry : hm.entrySet())
        {
            if (Integer.parseInt(String.valueOf(entry.getValue())) == 1)
                a.add(Integer.parseInt(String.valueOf(entry.getKey())));
        }

        // return a as an array
        return a.toArray(new int[a.size()]);
    }
    
    public static void main(String args[])
    {
            // A 2D may of integers with some duplicates

            int[][] m = { { 1, 2, 3, 4, 5 },
                            { 6, 7, 8, 9, 10 },
                            { 11, 12, 12, 14, 15 },
                            { 16, 17, 18, 18, 20 },
                            { 21, 22, 23, 24, 25 } };
    
            a = singleOccurence(m);
    }
}

【讨论】:

  • 太糟糕了,这是限制的一部分。来自 OP:“我只能使用循环(没有地图等)”
【解决方案3】:

最好使用布尔数组boolean[] dups 来跟踪重复的数字,因此在第一次通过时填充这个中间数组并计算单数。

然后创建适当大小的结果数组,如果该数组不为空,则在第二次迭代 dups 时将标记为单数的值复制到结果数组中。

public static int[] getSingles(int[][] arr) {
    int n = arr.length;
    int m = arr[0].length;
    boolean[] dups = new boolean[n * m];
    int singles = 0;
    for (int i = 0; i < dups.length; i++) {
        if (dups[i]) continue; // skip the value known to be a duplicate
        int curr = arr[i / m][i % m];
        boolean dup = false;
        for (int j = i + 1; j < dups.length; j++) {
            if (curr == arr[j / m][j % m]) {
                dup = true;
                dups[j] = true;
            }
        }
        if (dup) {
            dups[i] = true;
        } else {
            singles++;
        }
    }
    // debugging log
    System.out.println("singles = " + singles + "; " + Arrays.toString(dups));
    int[] res = new int[singles];
    if (singles > 0) {
        for (int i = 0, j = 0; i < dups.length; i++) {
            if (!dups[i]) {
                res[j++] = arr[i / m][i % m];
            }
        }
    }
    return res;
}

测试:

int[][] mat = {
    {2, 2, 3, 3},
    {4, 2, 0, 3},
    {5, 4, 2, 1}
};    
System.out.println(Arrays.toString(getSingles(mat)));

输出(包括调试日志):

singles = 3; [true, true, true, true, true, true, false, true, false, true, true, false]
[0, 5, 1]

【讨论】:

    【解决方案4】:

    您对previous 的使用只是一个即将出现的想法。删除它,并填充一维a。使用两个嵌套的 for 循环查找重复项需要 n4 个步骤。但是,如果您对数组 a 进行排序, - 对值进行排序 - 花费 n² log n²,您可以更快地找到重复项。

    Arrays.sort(a);
    int previous = a[0];
    for (int h = 1; h < a.length; ++h) {
        if (a[h] == previous)...
        previous = a[h];
     ...
    

    看起来这个解决方案已经在课堂上处理过了。

    【讨论】:

      【解决方案5】:

      看起来不太好:

      previous = m[i][j];
      
      if (m[i][j] != previous) {
          a[h] = m[i][j];
          h++;
      }
      

      您将m[i][j] 分配给previous,然后检查if (m[i][j] != previous) 是否?

      对于数字的来源范围,任务是否有任何限制?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-08
        • 2014-10-28
        • 1970-01-01
        • 1970-01-01
        • 2022-01-25
        • 1970-01-01
        • 2022-11-21
        相关资源
        最近更新 更多