Algorithm 荷兰国旗-推导解决方案

Algorithm 荷兰国旗-推导解决方案,algorithm,sorting,hash,hashtable,insertion-sort,Algorithm,Sorting,Hash,Hashtable,Insertion Sort,从Coursera的sedgewick学习了基本排序、选择排序、插入排序和堆排序 选择排序-最终排序顺序开始形成每次迭代 插入排序-升序(非最终)开始形成每次迭代 堆排序-插入排序的激进版本 在学习排序算法(如上所示)后,我在上述课程中有一个作业 荷兰国旗。给定一个n桶数组,每个桶包含一个红色、白色或蓝色的鹅卵石,按颜色对它们进行排序。允许的操作包括: swap(i,j):swap桶中的鹅卵石i与桶中的鹅卵石j color(i):桶中卵石的颜色i 性能要求如下: 最多n调用color() 至多

从Coursera的sedgewick学习了基本排序、选择排序、插入排序和堆排序

选择排序-最终排序顺序开始形成每次迭代

插入排序-升序(非最终)开始形成每次迭代

堆排序-插入排序的激进版本


在学习排序算法(如上所示)后,我在上述课程中有一个作业

荷兰国旗。给定一个
n
桶数组,每个桶包含一个红色、白色或蓝色的鹅卵石,按颜色对它们进行排序。允许的操作包括:

swap(i,j)
swap
桶中的鹅卵石
i
与桶中的鹅卵石
j

color(i)
:桶中卵石的颜色
i

性能要求如下:

最多
n
调用
color()

至多调用
swap()

恒定的额外空间


通过阅读这个问题,

从给定的性能要求中,我得到了一个提示,即
n
交换是必需的(最多)。从这个暗示,我想

(一) 插入排序,确保n个反转对进行n次交换

(二)
假设存储在桶中的颜色,如果给定n个桶,相似的颜色很有可能更接近。这导致了部分排序数组的情况,其中数组是部分排序的,如果要详细说明此问题的解决方案,反转数,则不需要提及算法

相反,熟悉快速排序的分区例程实现——这将非常有用

附言

堆排序-插入排序的激进版本

不,你错了,这是完全不同的方法


你可以考虑shell排序是如何利用INSERT排序INTERPROSSION/P>< P>来解决这个问题的,你不需要提到的算法。

相反,熟悉快速排序的分区例程实现——这将非常有用

附言

堆排序-插入排序的激进版本

不,你错了,这是完全不同的方法

你可以考虑shell排序如何在内部使用INSERT排序

< P>我不认为你应该(或需要)假设较近的桶有更高的机会拥有相同的颜色。这个问题可以通过保持三种颜色中第一次出现的两种(在排序中不被视为“第一”的颜色)的索引来解决。将颜色替换为值0、1、2,我相信此代码满足以下要求:

public class Z {
  private static int first1, first2;

  private static void swap(int[] v, int i, int j) {
    int tmp = v[i];
    v[i] = v[j];
    v[j] = tmp;
  }

  private static void sort(int[] v) {
    first1 = -1;
    first2 = -1;
    for(int i=0; i<v.length; i++) {
      switch(v[i]) {
        case 0:
          if (first1 != -1) {
            swap(v, i, first1);
            if (first2 != -1) {
              swap(v, i, first2);
              first2++;
            }
            first1++;
          } else if (first2 != -1) {
            swap(v, i, first2);
            first2++;
          }
          break;
        case 1:
          if (first2 != -1) {
            swap(v, i, first2);
            if (first1 == -1) {
              first1 = first2;
            }
            first2++;
          } else if (first1 == -1) {
            first1 = i;
          }
          break;
        case 2:
          if (first2 == -1) {
            first2 = i;
          }
          break;
      }
    }
  }
  public static String toString(int[] v) {
    StringBuilder sb = new StringBuilder();
    sb.append("[");
    for(int i=0; i<v.length; i++) {
      sb.append(v[i]);
      sb.append(" ");
    }
    sb.append("]");
    return sb.toString();
  }

  public static void main(String[] args) {
    int c = Integer.parseInt(args[0]);
    int[] v = new int[c];
    while(true) {
      int[] tmp = v.clone();
      System.out.print(toString(tmp) + "=>");
      sort(tmp);
      System.out.println(toString(tmp));
      int prev = -1;
      for(int j=0; j<tmp.length; j++) {
        if (tmp[j] < prev) {
          throw new Error();
        }
      }
      int j;
      for(j=0; j<c; j++) {
        v[j]++;
        if (v[j] == 3) {
          v[j] = 0;
        } else {
          break;
        }
      }
      if (j == c) {
        break;
      }
   }
  }
}
公共类Z{
私有静态int first1、first2;
私有静态无效交换(int[]v,int i,int j){
int tmp=v[i];
v[i]=v[j];
v[j]=tmp;
}
私有静态无效排序(int[]v){
第一个1=-1;
前2=-1;
对于(int i=0;i我认为您不应该(或不需要)假设距离越近的桶具有相同颜色的可能性越高。问题可以通过保持三种颜色中两种(在排序中未被视为“第一”的颜色)的第一次出现的索引来解决.将颜色替换为值0、1、2,我相信此代码满足以下要求:

public class Z {
  private static int first1, first2;

  private static void swap(int[] v, int i, int j) {
    int tmp = v[i];
    v[i] = v[j];
    v[j] = tmp;
  }

  private static void sort(int[] v) {
    first1 = -1;
    first2 = -1;
    for(int i=0; i<v.length; i++) {
      switch(v[i]) {
        case 0:
          if (first1 != -1) {
            swap(v, i, first1);
            if (first2 != -1) {
              swap(v, i, first2);
              first2++;
            }
            first1++;
          } else if (first2 != -1) {
            swap(v, i, first2);
            first2++;
          }
          break;
        case 1:
          if (first2 != -1) {
            swap(v, i, first2);
            if (first1 == -1) {
              first1 = first2;
            }
            first2++;
          } else if (first1 == -1) {
            first1 = i;
          }
          break;
        case 2:
          if (first2 == -1) {
            first2 = i;
          }
          break;
      }
    }
  }
  public static String toString(int[] v) {
    StringBuilder sb = new StringBuilder();
    sb.append("[");
    for(int i=0; i<v.length; i++) {
      sb.append(v[i]);
      sb.append(" ");
    }
    sb.append("]");
    return sb.toString();
  }

  public static void main(String[] args) {
    int c = Integer.parseInt(args[0]);
    int[] v = new int[c];
    while(true) {
      int[] tmp = v.clone();
      System.out.print(toString(tmp) + "=>");
      sort(tmp);
      System.out.println(toString(tmp));
      int prev = -1;
      for(int j=0; j<tmp.length; j++) {
        if (tmp[j] < prev) {
          throw new Error();
        }
      }
      int j;
      for(j=0; j<c; j++) {
        v[j]++;
        if (v[j] == 3) {
          v[j] = 0;
        } else {
          break;
        }
      }
      if (j == c) {
        break;
      }
   }
  }
}
公共类Z{
私有静态int first1、first2;
私有静态无效交换(int[]v,int i,int j){
int tmp=v[i];
v[i]=v[j];
v[j]=tmp;
}
私有静态无效排序(int[]v){
第一个1=-1;
前2=-1;

对于(int i=0;i乍一看,它看起来像是对桶排序的介绍:将每个红色圆石移动到红色数组中,将每个白色圆石移动到白色数组中,将每个蓝色圆石移动到蓝色数组中,然后将这3个数组复制到最终的输出数组中。简单的实现需要3*n次color()调用,2*n次swap()调用和n+恒定附加内存

但是限制是有点不允许的…我们负担不起简单的决定,我们负担不起临时数组的额外内存

请注意,n是输入数组的长度,而不是置换数,也不是乘以某个值。即:

  • swap()的每次调用都应该在其最终位置放置一个鹅卵石
  • 互换应该到位
  • 每次调用color()都会导致相应的swap()调用
在只有3种颜色的情况下是可能的。为了使之成为可能,我们可以将输入数组划分为3(4)个部分:

r) 数组开头的红色鹅卵石

w) 白卵石从一开始就是红卵石

u) 未加工的鹅卵石沿着白色鹅卵石一直延伸到蓝色鹅卵石

b) 数组末尾的蓝色鹅卵石

假设我们使用基于0的数组索引,那么索引[0]是数组的第一个元素,[n-1]是数组的最后一个元素

现在,为了跟踪数组状态,我们可以使用几个变量:

  • 变量r将保存处理过的红色卵石的数量

  • 变量w将保存处理过的白色卵石的数量

  • 变量b将保存处理过的蓝色鹅卵石的数量

  • 变量i将保存当前要处理的卵石索引(已处理)

这对于处理循环来说是不变的。在开始时,r=0,w=0,b=0,i=0。在结束时,r,w,b保存相应卵石的数量,i=n-b

因此,数组在开始时将如下所示:

uuuuuuuuuuuu ^ ^ r n=n-0=n-b uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu ^ ^ r n=n-0=n-b 在处理过程中,阵列将如下所示:

rrwwwuuuuuuub ^ ^ ^ r w+r n-b i RRWWWUUUB ^ ^ ^ RW+RN-b 我 Arrya最终会是这样的:

rrrwwwwwwbbbb ^ ^ ^ ^ 0 r n-b n w+r i RRRWWBBBB ^ ^ ^ ^ 0RN-BN w+r 我 处理循环的每一步(在此之后i递增)我们都会做出决策并执行以下三种可能的操作之一:

  • 如果a[i]为红色,我们交换(r,i)并增加r
  • 如果a[i]是白色的,我们增加w-实际上这是无用的动作,因为我们实际上不使用w,