Javascript检查列表是否在一次交换后排序

时间:2015-05-02 06:13:45

标签: javascript algorithm sorting swap

我想检查列表是否可以通过执行最多一个交换操作进行排序,如果有,我想返回true。否则,我想返回false

例如,输入

A = [1,2,3,4,5]

应该导致true因为它已经排序了。

A = [1,2,5,4,3]

应该导致true因为有一个交换,涉及5和3,列表就会被排序。

A = [1,2,5,3,4]

应该导致false,因为它需要多个交换才能排序。

我的代码如下。如果A已经排序,则返回true,但如果未排序,则返回undefined,但可以使用一个交换进行排序。

有人可以帮我找到问题吗?

    function solution(A) {
        var count=0;
        for(var k=0; k<A.length; k++) //check if sorted
        {
            if(A[k] <= A[k+1])
                count++;
            else
                break;
        }
        if (count === A.length - 1) //if already sorted return true
        {
            return true;
        }


        for(var i=0; i<A.length; i++)   //if not sorted lets check
        {
            var temp=0;
            for(var j=i+1; j<A.length; j++)
            {
               if(A[i] > A[j]) //swap only if A[i] > A[j]
               {
                    temp = A[i];
                    A[i] = A[j];
                    A[j] = temp;
//check if sorted
               }
            }
        }
    }

我想检查每次交换后是否对数组进行排序。我怎么能这样做?

4 个答案:

答案 0 :(得分:5)

尝试每个可能的交换并检查结果的天真方法相对于数组的长度需要O(n 3 )时间。找到第一个无序对并尝试通过交换每个后续元素来修复它的更聪明的方法需要O(n 2 )时间。对数组进行排序并将其与原始数据进行比较的方法需要O(n log n)时间。我们能做得更好吗?

是的,我们可以在线性时间内解决这个问题。我们首先寻找一对倒置的相邻元素,这意味着左边的那个元素比右边的元素大。如果没有这样的对,则数组已经排序。

否则,我们找到最左边这样的一对。让我们取这对中较大的元素,即左边的元素,并将其称为x。如果x是一系列相等元素的最后一个,那么让我们采用最左边的元素,因为当我们将x与较小的元素y交换时,我们希望y出现在每个元素等于x之前。

现在我们扫描倒置对的右侧,找到至少与x一样大的最早元素。一旦找到这样的元素,我们就会在它之前使用元素并调用此元素y。如果没有这样的元素,让y成为数组的最后一个元素。

如果可以在一次交换中对数组进行排序,则交换xy是必要且充分的。考虑一下案例:

  • 如果倒置对右侧的所有元素都小于x,则x必须移过所有元素。因此,我们将x与数组的最后一个元素交换。

  • 否则,请考虑x右侧所有大于x的元素。在排序数组中,x必须在所有数组之前出现,但x必须移过小于它的元素。因此,我们发现倒对的右侧最早的元素至少与x一样大,我们将x交换到它之前的位置。

// Returns true if and only if A can be sorted with at most one swap.
function almostSorted(A) {
  for (var i = 1; i < A.length; ++i) {
    // Look for an inverted adjacent pair.
    if (A[i-1] <= A[i]) {
      continue;
    }
    var x = A[i-1],
        left = i-1;
    // If x is one of a sequence of identical elements, take the leftmost.
    while (left-1 >= 0 && A[left-1] == x) {
      --left;
    }
    // Scan past the inverted pair for the earliest element no smaller than x.
    for (++i; i < A.length; ++i) {
      if (A[i] >= x) {
        break;  // If we never break here, i will be equal to A.length.
      }
    }
    // Let y be the element before the earliest element no smaller than x.
    var right = i-1,
        y = A[right];  
    // Swap x and y.
    A[left] = y;
    A[right] = x;
    // Is the array sorted now?
    for (i = (left == 0 ? 1 : left); i < A.length; ++i) {
      if (A[i-1] > A[i]) {
        return false;
      }
    }
    return true;  // One swap was enough to sort the array.
  }
  return true;  // The array is already sorted.
}

// A few tests.
function test(A) {
  document.write('['+A.join(', ')+']');
  var result = almostSorted(A);
  document.write(': <span class="', result, '">', result, '</span>');
  if (result) {
    document.write(' &rarr; ', '['+A.join(', ')+']');
  }
  document.write('<br />');
}
test([1, 2, 5, 4, 3]);
test([1, 2, 3, 5, 4]);
test([1, 4, 3, 2, 5]);
test([1, 5, 4, 3, 2]);
test([1, 5, 3, 3, 7]);
test([2, 2, 1, 3, 7]);
test([2, 3, 1, 3, 7]);
test([1, 3, 1, 3, 7]);
test([2, 1, 1, 3, 7]);
body {
  font-family: sans-serif;
  font-size: 17px;
  color: #333;
}
.false {
  color: #b23c3c;
}
.true {
  color: #5c7b51;
}

答案 1 :(得分:1)

see following example.
set it into a function. i used it in window onload

var a=[1,2,5,4,3];
var aTmp=a.slice(0);
aTmp.sort();
var cnt=0;
for(var i=0;i<a.length;i++){
   if(a[i]!=aTmp[i]){     
    cnt++;
   }
   if(cnt>2)
     return false;
}
if(cnt==0 || cnt==2)
    return true;
else
    return false;

答案 2 :(得分:0)

如果您不想对数组进行排序,最好计算arr [i]&gt;的次数。 arr [j](j&gt; i)并且如果count> = 1则返回。

将此作为辅助方法使用:

def next_highest(n)
  a = n.to_s.reverse.split('').map(&:to_i)
  last = -Float::INFINITY
  x,ndx = a.each_with_index.find { |d,i| res = d<last; last=d; res }
  return nil unless x
  swap_val = a[ndx]
  swap_ndx = (0...ndx).select { |i| a[i] > swap_val }.min_by{ |i| a[i] }
  a[ndx], a[swap_ndx] = a[swap_ndx], swap_val
  a[0...ndx] = a[0...ndx].sort.reverse
  a.join.reverse
end

next_highest(126531)       #=> "131256" 
next_highest(109876543210) #=> "110023456789" 

这是你的新功能:

function isArraySorted(arr){
      for(var i = 0; i < arr.length ; ++i) {
          if(arr[i] > arr[i+1])
              return false;
       }

       return true;
}

答案 3 :(得分:0)

这应符合您计划的目标

function solution(A) {
    // write your code in JavaScript (Node.js 0.12)
    var count=0;
    for(var k=0; k<A.length; k++) //check if sorted
    {
        if(A[k] <= A[k+1])
            count++;
        else
            break;
    }
    if (count === A.length - 1) //if already sorted return true
    {
        return true;
    } else {//swap once where its not in order
        for (var l = count+1; l<A.length;l++)
        {
            //Swap that and a subsequent element.
           var temp = A[count];
           A[count] = A[l];
           A[l] = temp;

           c = 0;
           for(var k=0; k<A.length; k++) //check if sorted
           {
              if(A[k] <= A[k+1])
                 c++;
              else
                 break;
            }
            if (c === A.length - 1) //if already sorted return true
            {
                 return true;
            }
            //Swap them back
            var temp = A[count];
            A[count] = A[l];
            A[l] = temp;
        }
    }
    return false;
}