【问题标题】:How can I re-sort a sorted array by absolute values, in linear time?如何在线性时间内按绝对值重新排序排序数组?
【发布时间】:2015-05-30 18:50:31
【问题描述】:

给定一个包含负值和正值的排序数组。使用负数绝对值的数组。你的复杂度应该是 O(n)

示例输入

[-8, -5, -3, -1, 3, 6, 9]

预期输出

[ -1, -3, 3, -5, 6, -8, 9 ]

到目前为止我已经这样做了,但是输出不正确。

function sortMe(input) {
   var newArr = [];
   for (var i = 0; i < input.length; i++) {
     var value = Math.abs(input[i]);
     newArr.push(value);
   }
   var c = newArr.sort()
}

它正在输出

[ 1, 3, 3, 5, 6, 8, 9 ]

【问题讨论】:

    标签: javascript arrays sorting


    【解决方案1】:
    1. 将数组分成两半,一为负数,另一半为正数。

    2. 反转负数数组。

    3. 然后,使用两个数组的绝对值运行merging algorithm

    总体运行时复杂度仍为 O(n)。


    function sortMe(sortedArray) {
    
      var idx = -1, negs, pos, result = [], nIdx = 0, pIdx = 0;
    
      if (sortedArray.length === 0)
        return result;
    
      // Find the index where positive elements begin
      while (idx < sortedArray.length && sortedArray[++idx] < 0);
    
      // Get elements till the index and reverse the array
      negs = sortedArray.slice(0, idx).reverse();
    
      // Get elements from the index till the end
      pos = sortedArray.slice(idx);
    
      // Merging algorithm implementation which merges `negs` and `pos`
      while (nIdx < negs.length || pIdx < pos.length)
      {
        if (nIdx < negs.length && pIdx < pos.length)
        {
          if (Math.abs(negs[nIdx]) <= pos[pIdx])
            result.push(negs[nIdx++]);
          else
            result.push(pos[pIdx++]);
        }
        else if (nIdx < negs.length)
          result.push(negs[nIdx++]);
        else
          result.push(pos[pIdx++]);
      }
    
      return result;
    }
    
    console.log(sortMe([-8, -5, -3, -1, 3, 6, 9]));
    // [ -1, -3, 3, -5, 6, -8, 9 ]
    

    function sortMe(sortedArray) {
    
      var idx = -1, negs, pos, result = [], nIdx = 0, pIdx = 0;
    
      if (sortedArray.length === 0)
        return result;
    
      // Find the index where positive elements begin
      while (idx < sortedArray.length && sortedArray[++idx] < 0);
    
      // Get elements till the index and reverse the array
      negs = sortedArray.slice(0, idx).reverse();
    
      // Get elements from the index till the end
      pos = sortedArray.slice(idx);
    
      // Merging algorithm implementation which merges `negs` and `pos`
      while (nIdx < negs.length || pIdx < pos.length)
      {
        if (nIdx < negs.length && pIdx < pos.length)
        {
          if (Math.abs(negs[nIdx]) <= pos[pIdx])
            result.push(negs[nIdx++]);
          else
            result.push(pos[pIdx++]);
        }
        else if (nIdx < negs.length)
          result.push(negs[nIdx++]);
        else
          result.push(pos[pIdx++]);
      }
    
      return result;
    }
    
    function getElement(id) {
      return document.getElementById(id);
    }
    
    function sorter() {
      var data = getElement("numbers").value.split(" ").map(Number);
      getElement("result").innerHTML = "[" + sortMe(data).join(", ") + "]";
    }
    <input id="numbers" value="-8 -5 -3 -1 3 6 9" />
    <input type="button" onclick="sorter()" value="Click here to Sort" />
    <pre id="result" />

    【讨论】:

      【解决方案2】:
      int[] arr = new int[] { -8, -5, -3, -1, 3, 6, 9 };
      for(int i = 0; i < arr.length; i++) {
          int pos = 0;                
          for (int j = 0; j < arr.length; j++) {
              if (Math.abs(arr[pos]) > Math.abs(arr[j])) {
                  int temp;
                  temp = arr[pos];
                  arr[pos] = arr[j];
                  arr[j] = temp;
                  pos++;
              }
          }  
      }
      

      【讨论】:

        【解决方案3】:

        可以通过考虑3种情况来完成:

        一个。所有正数:保持数组不变

        b.所有负数:反转数组

        c。正数和负数:在输入数组中找到最后一个负数,然后使用左右比较。

        import java.util.Arrays;
        
        public class SortAbsoluteValue {
            // all positive; all negative; postive & negative
            public static void main(String[] args) {
                int[] num = new int[] { -8, -5, -3, -1, 3, 6, 9 };
                int[] result = sortAbsolute(num);
        
                for (int i = 0; i < num.length; i++) {
                    System.out.println(result[i]);
                }
            }
        
            private static int[] sortAbsolute(int[] num) {
                int size = num.length;
                // all positive : leave as is
                if (num[0] >= 0)
                    return num;
                // all negative : reverse array
                if (num[size-1] < 0) {
                    int[] temp = Arrays.copyOf(num, num.length);
                    Arrays.sort(temp);
                    return temp;
                }
                int[] result = new int[size];
        
                int i = 0;
                for (i = 0; i < size - 1; i++) {
                    if (num[i] < 0 && num[i + 1] >= 0) {
                        break;
                    }
                }
        
                int left = i - 1;
                int right = i + 1;
                result[0] = num[i];
                int k = 0;
                while (left >= 0 && right < size) {
                    if (Math.abs(num[left]) < num[right]) {
                        result[++k] = num[left];
                        left--;
                    } else {
                        result[++k] = num[right];
                        right++;
                    }
                }
                // remaining left elements, if any
                while(left>=0) {
                    result[++k] = num[left--];
                }
                // remaining right elements, if any
                while(right<size) {
                    result[++k] = num[right++];
                }
                return result;
            }
        }
        

        【讨论】:

          【解决方案4】:

          @thefourtheye,您的解决方案非常好,但它不能更正混合数字(正数和负数)的处理数字序列。 您可以使用下一个序列检查您的解决方案,例如: [-2 -5 3 8 -10] 它会给你错误的结果:[3, -5, -2, 8, -10]。

          这是因为:

          1) 您认为负数和正数应该按排序顺序排列。

          2) 找出正数和负数的索引,尽管它们可能不一致。

          我已经更正了您的代码,现在它可以处理任何混合的正数/负数序列并按绝对值正确排序。代码如下:

          function sortArrayByAbsValues(sortedArray) {
          
                          var negs = [], pos = [], result = [], nIdx = 0, pIdx = 0;
          
                          if (sortedArray.length === 0)
                              return result;
          
                          //prepare negative/positive number sequences.
                          for (var i = 0; i < sortedArray.length; i++) {
                              var value = sortedArray[i];
                              if (value < 0) {
                                  negs.push(value);
                              } else {
                                  pos.push(value);
                              }
                          }
                          // sort positive/negative numbers
                          pos = pos.sort();
                          negs = negs.sort();
          
                          // Merging algorithm implementation which merges `negs` and `pos`
                          while (nIdx < negs.length || pIdx < pos.length) {
                              if (nIdx < negs.length && pIdx < pos.length) {
                                  if (Math.abs(negs[nIdx]) <= pos[pIdx])
                                      result.push(negs[nIdx++]);
                                  else
                                      result.push(pos[pIdx++]);
                              }
                              else if (nIdx < negs.length)
                                  result.push(negs[nIdx++]);
                              else
                                  result.push(pos[pIdx++]);
                          }
          
                          return result;
                      }
          

          【讨论】:

          • 这不是问题所在。初始数组已排序。为什么数字会混在一起?所有负数都是连续的,然后是所有正数。
          【解决方案5】:
          inputArray.sort(function(a,b) {
              return Math.abs(a) - Math.abs(b);
          });
          

          可能不是 O(n),但对我来说效果很好

          【讨论】:

            【解决方案6】:

            你可以简单地使用冒泡排序来实现这一点

             var array= new Array(2,-2,3,5,-3,1);
            
             function absoluteSortin(array){
            
                var inputArray= array.slice(0);
                var temp;
            
                for(var i=0;i< inputArray.length;i++){
                    for(j=i+1; j<inputArray.length;j++){
                        if(Math.abs(inputArray[i]) > Math.abs(inputArray[j])){
                            temp= inputArray[j];
                            inputArray[j] = inputArray[i];
                            inputArray[i] = temp;
                        }
                    }
                }
               return inputArray;
            
             }
             absoluteSortin(array);
            

            【讨论】:

              【解决方案7】:
              <?php
              $a = array(-2,-3,0,5,4,1,6,9,7,-9,-1,3);
              for($i=0;$i<count($a)-1;$i++) {
                  for($j=0;$j<count($a)-1;$j++){
                      $data1=abs($a[$j]);
                      $data2=abs($a[$j+1]);
                      if($data1>$data2) {
                          $temp = $a[$j];
                          $a[$j] = $a[$j+1];
                          $a[$j+1] = $temp;
                      }
                  }
              }
              echo "<pre>";
              print_R($a);
              ?>
              

              【讨论】:

                【解决方案8】:

                这是 Python 中的代码

                    def sorted_array(list1):
                        list_negative=[]
                        list_positive=[]
                
                        for i in list1:
                        if i<0:
                            list_negative.append(i)
                        else:
                            list_positive.append(i)
                
                        list_negative.reverse()    
                
                        for i in list_negative:
                            for j in range(0, len(list_positive)):
                                if abs(i)<=list_positive[j]:
                                    list_positive.insert(j,i)
                                    break
                        print(list_positive)    
                    list1=[-8,-5,-3,-1,3,6,9,-4]    
                    sorted_array(list1)
                

                【讨论】:

                  【解决方案9】:

                  两个指针方法。

                  void resort(vector<int> &a){
                  
                     int par ; // partition index (when +ve elements starts)
                  
                     // lets find where positive elements starts
                     for(int i = 0; i < a.size(); i++){
                        if(a[i] >= 0) {
                           par = i;
                           break;
                        }
                     }
                  
                    int l = par-1; // left of par
                    int r = par;   // right side
                  
                    vector<int> b; // extra array for answer
                  
                   
                    // compare left and right side element
                    // if any of them is lesser push that element in extra array i.e 'b'
                    while(l >= 0 and r < a.size()) {
                  
                       if(abs(a[l]) > a[r]) {
                          b.push_back(a[r]);
                          r++;
                       }
                       else if(abs(a[l]) < a[r]){
                          b.push_back(a[l]);
                          l--;
                       }
                       else{
                          b.push_back(a[l]);
                          l--;
                       }
                    }
                  
                   // push remaing element from both side
                   // like merge sort
                  
                    while(l >= 0) {
                      b.push_back(a[l]);
                      l--;
                    }
                    while(r < a.size()) {
                       b.push_back(a[r]);
                       r++;
                    }
                  
                    // print modified answer
                    for(auto x:b) {
                       cout<<x<<" ";
                    }
                  }
                  

                  时间完成O(N)

                  Space Compl. O(N)

                  【讨论】:

                  • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation 将通过展示为什么这是解决问题的好方法,并使其对有其他类似问题的未来读者更有用,从而大大提高其长期价值。请edit您的回答添加一些解释,包括您所做的假设。
                  【解决方案10】:

                  你可以在 Python 中使用一行代码

                  nums = [-8, -5, -3, -1, 3, 6, 9]
                  
                  print(sorted(nums,key=abs))
                  

                  输出将是

                  [-1, -3, 3, -5, 6, -8, 9]
                  

                  【讨论】:

                    猜你喜欢
                    • 2014-03-27
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-04-11
                    • 1970-01-01
                    • 2020-12-23
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-08-31
                    相关资源
                    最近更新 更多