[英]How can I re-sort a sorted array by absolute values, in linear time?
您將獲得一個包含負值和正值的排序數組。 使用負數絕對值的數組。 你的復雜度應該是 O(n)
樣本輸入
[-8, -5, -3, -1, 3, 6, 9]
預計 Output
[ -1, -3, 3, -5, 6, -8, 9 ]
到目前為止我已經這樣做了,但是 output 是不正確的。
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()
}
它給了 output
[ 1, 3, 3, 5, 6, 8, 9 ]
將數組分成兩半,一個是負數,另一半是正數。
反轉負數數組。
然后,使用兩個數組的絕對值運行合並算法。
總體運行時復雜度仍然是 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" />
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種情況來完成:
一種。 所有正數:保持數組不變
灣所有負數:反轉數組
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;
}
}
@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;
}
inputArray.sort(function(a,b) {
return Math.abs(a) - Math.abs(b);
});
可能不是 O(n) 但對我來說效果很好
您可以使用冒泡排序簡單地實現這一點
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);
?>
這是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)
兩個指針的方法。
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<<" ";
}
}
時間完成在)
空間組合在)
您可以使用 Python 中的一行
nums = [-8, -5, -3, -1, 3, 6, 9]
print(sorted(nums,key=abs))
output 將是
[-1, -3, 3, -5, 6, -8, 9]
這是一個快速的解決方案
拆分列表分為兩部分,第一部分為負數,第二個列表將包含正數
應用合並算法來合並 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; }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.