【问题标题】:Java finding the smallest integer in a speciofic position in a sets of integerJava在一组整数中找到特定位置的最小整数
【发布时间】:2021-09-19 12:48:55
【问题描述】:

算法:

Procedure SELECT( k,S)
{ if ISI =1 then return the single element in S
   else { choose an element a randomly from S;
              let S1,S2,and S3 be he sequences of elements in S  
              less than, equal to, and greater than m, respectively;
             if IS1I >=k then return SELECT(k,S1)
              else
                   if (IS1I + IS2I >=k then return m
                   else return SELECT(k-IS1I-IS2I , S3);
             }
}

问题是实现第一个算法以在一组整数中找到第 k 个最小的整数,并针对随机数生成器生成的不同整数组测试您的程序。 以下是我的解决方案。

import java.util.Random;
import java.util.Scanner;

public class main {
    private static Random rand = new Random();
    private static Scanner keyboard = new Scanner(System.in);

    public static int firstAlgorithm(int k, int[] S) {
        int m = S[rand.nextInt(S.length)];
        int[] S1 = new int[S.length];
        int[] S2 = new int[S.length];
        int[] S3 = new int[S.length];
        int p = 0;
        int q = 0;
        int r = 0;

        if (S.length == 1)
            return S[0];

        for (int i = 0; i < S.length; i++) {
            if (S[i] < m) {
                S1[p] = S[i];
                p++;
            } else if (S[i] == m) {
                S2[q] = S[i];
                q++;
            } else {
                S3[r] = S[i];
                r++;
            }
        }

        S1 = trimToSize(S1, p);
        S2 = trimToSize(S2, q);
        S3 = trimToSize(S3, r);

        if (S1.length >= k)
            return firstAlgorithm(k, S1);
        else if (S1.length + S2.length >= k)
            return m;
        else
            return firstAlgorithm(k - S1.length - S2.length, S3);
    }

    private static int[] trimToSize(int[] arr, int size) {
        int[] temp = new int[size];
        for (int i = 0; i < size; i++) {
            temp[i] = arr[i];
        }
        return temp;
    }

    public static void printArray(int[] S) {
        for (int i = 0; i < S.length; i++) {
            System.out.print(S[i] + "\t");
            if (i % 10 == 9)
                System.out.println();
        }
    }

    // start main method
    public static void main(String[] args) {
        System.out.print("Enter the size of an array: ");
        int size = keyboard.nextInt();
        while (size < 1) {
            System.out.println("Size of the array should be greater than 0.");
            System.out.print("Enter the size of an array: ");
            size = keyboard.nextInt();
        }

        System.out.print("Enter the value of k: ");
        int k = keyboard.nextInt();
        while (k < 1 || k > size) {
            System.out.println("Value of k should be in the range 1-" + size + ".");
            System.out.print("Enter the value of k: ");
            k = keyboard.nextInt();
        }

        int[] S = new int[size];
        for (int i = 0; i < size; i++) {
            S[i] = 100 + rand.nextInt(900);
        }

        System.out.println("\nRandom values generated in the array:");
        printArray(S);
        System.out.println();
        System.out.println(k + "th smallest value in the array using Algorithm #1: " + firstAlgorithm(k, S));

    }
}

但我需要在不使用临时数组进行分区的情况下实现上述算法。我该怎么做?

【问题讨论】:

  • 如果你的输入是:1, 4, 2, 6, 2 and k = 2 它的输出应该是什么?
  • 答案应该是 2,因为该数组的第二小是 2
  • (就地)分区算法与快速排序中的相同。你可以在这里找到伪代码:en.wikipedia.org/wiki/Quicksort#Lomuto_partition_scheme
  • 请注意,您的算法是递归的,我认为 java 不会进行 tall-call 优化。这意味着在编写时,您的代码可能占用 O(n) 空间(在堆栈上)。您还应该摆脱“trimToSize”并使用数组视图(例如:stackoverflow.com/questions/39218468/…)。自己维护高低指数是列表子视图的一种简单而好的替代方法。
  • @Paul Hankin。我刚刚更新到上面给定的算法。

标签: java algorithm sorting


【解决方案1】:

算法是 Dijkstra 的 3 路分区。

你将不得不修改原来的 S。

未测试的(伪)代码

public static int partition(int left, int right, int[] S) {
  int m = rand.nextInt(right-left);  // protect against malicious data
  swap(S[left+m], S[right]);
  int equal = left;

  while (left < right) {
    if (a[left] < a[n])
      swap(S, left++, equal++)
    else if (a[left] == a[n]) 
      swap(S, left, --right);
    else 
      left++;
  }

  return left, equal;
}


public static int firstAlgorithm(int k, int left, int right, int[] S) {
  if (left == right)
     return S[left];

  int p, e = partition(left, right, S); // returns 2 values. S1=[0,p), S2=[p,e), S3=[e, n)

  if (p >= k)
    return firstAlgorithm(k, left, p, S);
  else if (e >= k)  // p < k
     return S[p]; // p is the first equal, e is first larger than equal
  else // e < k
    return firstAlgorithm(k, e, right, S);
}


// test
S = {1, 4, 2, 6, 2};
k = 2;
int result = firstAlgorithm(2, 0, S.length-1, S);
assert(result == 2);

保证警告语法和非一错误。

here在java中返回2个值的多种方式。

【讨论】:

    猜你喜欢
    • 2022-08-10
    • 2018-09-10
    • 2013-01-28
    • 2015-05-02
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多