如何确定单个交换是否足以对整数数组进行排序。

时间:2015-07-22 04:13:21

标签: java algorithm sorting

以下是代码片段,效率不高,请提供解决此问题的有效方法:

如果仅使用单个交换对数组进行排序,则此方法返回true。 如果数组需要多个交换操作进行排序,则此方法返回false。

public boolean sortArrayWithSingleSwapIfPossible() {
        int[] A = {1, 5, 3, 3, 2, 6};
        int temp;
        int swapCount = 0;
        int length = A.length;
        for (int i = 0; i < A.length; i++) {
            if (i == length - 1) {
                break;
            }
            if (A[i] > A[i + 1]) {
                if (((i + 2) < length) && A[i + 1] == A[i + 2]) {
                    temp = A[i];
                    A[i] = A[i + 2];
                    A[i + 2] = temp;
                    ++swapCount;

                } else {
                    temp = A[i];
                    A[i] = A[i + 1];
                    A[i + 1] = temp;
                    ++swapCount;
                }
            }

            if (swapCount > 1) {
                return false;
            }
        }
        return true;
    }

2 个答案:

答案 0 :(得分:3)

您可以尝试使用此O(N)解决方案。

  
      
  1. 从左起,找到第一个乱序元素。 O(N)
  2.   
  3. 从右边开始,找到第一个乱序元素。 O(N)
  4.   
  5. 交换这两个
  6.   
  7. 现在检查数组是否已排序。 O(N)
  8.   
public yourFunction(){
   int[] input = {1,5,3,3,2,6};
   int leftIndex = findLeftIndex(input);
   int rightIndex = findRightIndex(input);
   if( leftIndex == rightIndex || leftIndex ==-1 || rightIndex == -1)
       return false; // check these edge cases just to be on safe side.
   swap(input,leftIndex,rightIndex);
   return isSorted(input)
}

private int findRightIndex(int[] input) {
   for(int i=input.length -1 ; i>=1 ;i--){
      if(input[i-1] > input[i]){
        return i;
      }
   }
   return -1;
}

private int findLeftIndex(int[] input) {
    for(int i=0 ; i<(input.length-1) ;i++){
       if(input[i] > input[i+1]){
        return i;
       }
    }
    return -1;
} 

public boolean isSorted(int[] a){
   for(int i = 0; i < a.length-1; i ++){ 
     if (a[i] > a[i+1]) {
       return false; 
     }
   }
   return true; 
}

在您的示例中,

  1. 您会找到5
  2. 您会找到2
  3. swap 5,2 - &gt; {1,2,3,3,5,6}
  4. 检查数组是否已排序,它已排序,因此返回true
  5. <强>更新

    如果有重复的left_out_of_order元素或right_out_of_order元素,您可能需要将最左边的left_out_of_order元素与最右边的out_of_order_element进行交换。

    因此,您的findLeftIndex()findRightIndex()方法将更改如下:

    private int findRightIndex(int[] input) {
       for(int i=input.length -1 ; i>=1 ;i--){
          if(input[i-1] > input[i]){
            while(i<input.length-1 && input[i] == input[i+1]){
               i++;
            }
            return i;
          }
       }
       return -1;
    }
    
    private int findLeftIndex(int[] input) {
        for(int i=0 ; i<(input.length-1) ;i++){
           if(input[i] > input[i+1]){
            while(i>0 && input[i] == input[i-1]){
               i--;
            }
            return i;
           }
        }
        return -1;
    }
    

答案 1 :(得分:0)

解决方案 1:简单的方法

  1. 复制到新数组并排序

  2. 如果有任何差异除以 2 ~ 交换次数,则与原始数组进行比较

    static boolean checkSorted(int n, int arr[])
    {
        // Create a sorted copy of original array
        int []b = new int[n];
        for (int i = 0; i < n; i++)
            b[i] = arr[i];
        Arrays.sort(b, 0, n);
    
        // Check if 0 or 1 swap required to
        // get the sorted array
        int ct = 0;
        for (int i = 0; i < n; i++)
            if (arr[i] != b[i])
                ct++;
        if (ct/2 < 2)
            return true;
        else
            return false;
    

    }

source

解决方案 2:更有效。

  1. 从左向右移动

  2. 如果发现反例,则与其余的最小值交换(使用TreeMap进行排序,同时保留其索引)

  3. 增加交换计数器

  4. 继续旅行

  5. 如果发现反例返回 false

  6. 如果没有找到任何案例,则返回 true。

    私有静态布尔测试2(int[]输入){ int swapCounter = 0; for (int i = 0; i < input.length - 1; i++) { 如果(输入[i] > 输入[i+1]){ 如果(swapCounter > 0)返回false; TreeMap map = new TreeMap(); for (int j = i + 1; j < input.length; j++) { map.put(inputs[j], j); } int minIndex = (int)map.firstEntry().getValue(); int temp = 输入[i]; 输入[i] = 输入[minIndex]; 输入[minIndex] = 温度; 交换计数器++; } } 返回真; }