最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I re-sort a sorted array by absolute values, in linear time? - Stack Overflow

programmeradmin3浏览0评论

You are given a sorted array containing both negative and positive values. Resort the array taking absolute value of negative numbers. Your complexity should be O(n)

Sample Input

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

Expected Output

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

I have done this till now, but output is not correct.

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()
}

and it is giving output

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

You are given a sorted array containing both negative and positive values. Resort the array taking absolute value of negative numbers. Your complexity should be O(n)

Sample Input

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

Expected Output

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

I have done this till now, but output is not correct.

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()
}

and it is giving output

[ 1, 3, 3, 5, 6, 8, 9 ]
Share Improve this question edited May 30, 2015 at 19:28 thefourtheye 239k53 gold badges465 silver badges500 bronze badges asked May 30, 2015 at 18:50 Bhushan GoelBhushan Goel 2,1443 gold badges19 silver badges31 bronze badges 0
Add a comment  | 

11 Answers 11

Reset to default 9
  1. Split the array in to two halves, one with negative numbers and the other with positive numbers.

  2. Reverse the negative numbers array.

  3. Then, run merging algorithm with the absolute value of both the arrays.

Overall runtime complexity is still 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" />

Can be done by taking in mind 3 cases:

a. All positive numbers : leave the array as is

b. All negative numbers : reverse the array

c. Positive as well as negative numbers : find last negative number in input array and then use left and right to compare.

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;
    }
}

@thefourtheye, your solution is very good, but it does not correct process number sequences where numbers(positive and negative ones) are mixed. You can check your solution with the next sequence, for example: [-2 -5 3 8 -10] and it will give you wrong result : [3, -5, -2, 8, -10].

This is because:

1) You rely that negative and positive numbers should go in the sorted order.

2) Find indexes of positive and negative numbers despite the fact that they can go inconsistently.

I've corrected your code and now it can process any mixed positive/negative number sequences and correctly sort them by absolute values. Code is below:

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;
            }

You can simply achieve this using Bubble sort

 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);
<?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);
?>

Here is the code in 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)

two pointer approach.

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<<" ";
  }
}

Time Compl. O(N)

Space Compl. O(N)

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++;
        }
    }  
}

You can do with one line in Python

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

print(sorted(nums,key=abs))

The output will be

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

here is a quick solution

  • break list in two part first part negative and second list will contains positive number

  • apply merge algorithm to merge both list example in c#-.

    List<int> neg = arr.Where(x => x < 0).Reverse().ToList();
    List<int> pos = arr.Where(x => x > 0).ToList();
    var res=merge(neg,pos);    
    
     private static List<int> merge(List<int> left, List<int> right)
          {
              List<int> result = new List<int>();
    
              while (left.Count > 0 || right.Count > 0)
              {
                  if (left.Count > 0 && right.Count > 0)
                  {
                      if (Math.Abs(left.First()) <= right.First())  
                      {
                          result.Add(left.First());
                          left.Remove(left.First());     
                      }
                      else
                      {
                          result.Add(right.First());
                          right.Remove(right.First());
                      }
                  }
                  else if (left.Count > 0)
                  {
                      result.Add(left.First());
                      left.Remove(left.First());
                  }
                  else if (right.Count > 0)
                  {
                      result.Add(right.First());
    
                      right.Remove(right.First());
                  }
              }
              return result;
          }
    
inputArray.sort(function(a,b) {
    return Math.abs(a) - Math.abs(b);
});

Might not be O(n) but worked well for me

发布评论

评论列表(0)

  1. 暂无评论