lấy số gần nhất ra khỏi mảng


163

Tôi có một số từ âm 1000 đến 1000 và tôi có một mảng có số trong đó. Như thế này:

[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]

Tôi muốn số tôi đã thay đổi thành số gần nhất của mảng.

Ví dụ tôi lấy 80số tôi muốn lấy 82.


2
Không thể đơn giản: đặt một biến x, đi qua từng mảng một, so sánh ivới số hiện tại trong mảng, nếu chênh lệch giữa nó và inhỏ hơn giá trị hiện tại x, được đặt thành xsố mảng hiện tại. Khi kết thúc, xcó số gần nhất itừ mảng.
lừa dối

Câu trả lời:


208

Phiên bản ES5:

var counts = [4, 9, 15, 6, 2],
  goal = 5;

var closest = counts.reduce(function(prev, curr) {
  return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
});

console.log(closest);


1
Nhược điểm là nó chỉ hoạt động nếu cuộc gọi lại của less được gọi từ cùng phạm vi với các vars đã khai báo. Vì bạn không thể vượt qua goalđể giảm bớt, bạn phải tham chiếu nó từ phạm vi toàn cầu.
7yl4r

5
cũng có thể sử dụng hàm bậc cao hơn để làm điều đó.
dmp

3
@ 7yl4r hoặc bọc nó trong một chức năng? ;)
Đa Minh

1
@ 7yl4r không thực sự ... bạn có thể sử dụng liên kết để đạt được điều này ... ---------- // bộ giảm hàm chức năng (mục tiêu, trước, dòng) mục tiêu) <Math.abs (trước - mục tiêu)? current: trước); } // main.js var đếm = [4, 9, 15, 6, 2], Goal = 5; Counts.reduce (lesser.bind (null, mục tiêu)); ---------- Tôi không biết cách đặt mã trong các bình luận hahaha.
Mauricio Soares

Điều này lặp đi lặp lại trên mỗi mục không tối ưu nếu danh sách được sắp xếp nhưng ok cho danh sách nhỏ. Ngay cả khi không có tìm kiếm nhị phân, một vòng lặp có thể thoát nếu số tiếp theo là cách xa hơn.
Đaminh

144

Đây là mã giả có thể chuyển đổi thành bất kỳ ngôn ngữ thủ tục nào:

array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
number = 112
print closest (number, array)

def closest (num, arr):
    curr = arr[0]
    foreach val in arr:
        if abs (num - val) < abs (num - curr):
            curr = val
    return curr

Nó chỉ đơn giản là tìm ra sự khác biệt tuyệt đối giữa số đã cho và từng phần tử mảng và trả lại cho bạn một trong những phần tử có sự khác biệt tối thiểu.

Đối với các giá trị mẫu:

number = 112  112  112  112  112  112  112  112  112  112
array  =   2   42   82  122  162  202  242  282  322  362
diff   = 110   70   30   10   50   90  130  170  210  250
                         |
                         +-- one with minimal absolute difference.

Để chứng minh khái niệm, đây là mã Python tôi đã sử dụng để thể hiện điều này trong hành động:

def closest (num, arr):
    curr = arr[0]
    for index in range (len (arr)):
        if abs (num - arr[index]) < abs (num - curr):
            curr = arr[index]
    return curr

array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
number = 112
print closest (number, array)

Và, nếu bạn thực sự cần nó trong Javascript, hãy xem bên dưới để biết tệp HTML hoàn chỉnh thể hiện chức năng đang hoạt động:

<html>
    <head></head>
    <body>
        <script language="javascript">
            function closest (num, arr) {
                var curr = arr[0];
                var diff = Math.abs (num - curr);
                for (var val = 0; val < arr.length; val++) {
                    var newdiff = Math.abs (num - arr[val]);
                    if (newdiff < diff) {
                        diff = newdiff;
                        curr = arr[val];
                    }
                }
                return curr;
            }
            array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
            number = 112;
            alert (closest (number, array));
        </script>
    </body>
</html>

Bây giờ hãy nhớ rằng có thể có phạm vi để cải thiện hiệu quả nếu, ví dụ, các mục dữ liệu của bạn được sắp xếp (có thể được suy ra từ dữ liệu mẫu nhưng bạn không nói rõ). Bạn có thể, ví dụ, sử dụng tìm kiếm nhị phân để tìm mục gần nhất.

Bạn cũng nên nhớ rằng, trừ khi bạn cần thực hiện nhiều lần trong một giây, các cải tiến hiệu quả sẽ hầu như không được chú ý trừ khi bộ dữ liệu của bạn nhận được nhiều lớn hơn .

Nếu bạn làm muốn thử nó như vậy (và có thể đảm bảo mảng được sắp xếp theo thứ tự tăng dần), đây là một tốt điểm bắt đầu:

<html>
    <head></head>
    <body>
        <script language="javascript">
            function closest (num, arr) {
                var mid;
                var lo = 0;
                var hi = arr.length - 1;
                while (hi - lo > 1) {
                    mid = Math.floor ((lo + hi) / 2);
                    if (arr[mid] < num) {
                        lo = mid;
                    } else {
                        hi = mid;
                    }
                }
                if (num - arr[lo] <= arr[hi] - num) {
                    return arr[lo];
                }
                return arr[hi];
            }
            array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
            number = 112;
            alert (closest (number, array));
        </script>
    </body>
</html>

Về cơ bản, nó sử dụng dấu ngoặc và kiểm tra giá trị trung bình để giảm một nửa dung lượng giải pháp cho mỗi lần lặp, một O(log N)thuật toán cổ điển trong khi tìm kiếm tuần tự ở trên là O(N):

0  1  2   3   4   5   6   7   8   9  <- indexes
2 42 82 122 162 202 242 282 322 362  <- values
L             M                   H  L=0, H=9, M=4, 162 higher, H<-M
L     M       H                      L=0, H=4, M=2, 82 lower/equal, L<-M
      L   M   H                      L=2, H=4, M=3, 122 higher, H<-M
      L   H                          L=2, H=3, difference of 1 so exit
          ^
          |
          H (122-112=10) is closer than L (112-82=30) so choose H

Như đã nói, điều đó không tạo ra nhiều sự khác biệt cho các bộ dữ liệu nhỏ hoặc cho những thứ không cần phải nhanh chóng, nhưng đó là một lựa chọn bạn có thể muốn xem xét.


2
@micha, tôi đã thêm mã JS eqivalent vào câu trả lời, chỉ mất một lúc để thay đổi ngôn ngữ từ ngôn ngữ mà tôi đã quen với :-)
paxdiablo

2
Thời gian chạy kém cho thuật toán này nếu bạn có bộ dữ liệu lớn.
ylun.ca

4
@ ylun.ca, vì không có tuyên bố rõ ràng nào trong câu hỏi rằng dữ liệu được sắp xếp (ví dụ được sắp xếp nhưng có thể là trùng hợp), bạn không thể có hiệu quả tốt hơn O (n). Trong mọi trường hợp, đối với một tập dữ liệu có kích thước đó, hiệu quả chủ yếu là không liên quan. Nhưng quan điểm của bạn là hợp lệ vì vậy tôi sẽ thêm ghi chú vào hiệu ứng đó để hy vọng câu trả lời hoàn chỉnh hơn.
paxdiablo

1
Cảm ơn bạn tôi ước tôi có thể nâng cao hơn một lần! Nhiều câu trả lời hơn về stack stack nên đặt loại nỗ lực này vào chúng.
Richard Vanbergen

48

Phiên bản ES6 (2015):

const counts = [4, 9, 15, 6, 2];
const goal = 5;

const output = counts.reduce((prev, curr) => Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);

console.log(output);

Để sử dụng lại, bạn có thể sử dụng chức năng cà ri hỗ trợ giữ chỗ ( http://ramdajs.com/0.19.1/docs/#curry hoặc https://lodash.com/docs#curry ). Điều này mang lại rất nhiều sự linh hoạt tùy thuộc vào những gì bạn cần:

const getClosest = curry((counts, goal) => {
  return counts
    .reduce((prev, curr) => Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
});

const closestTo5 = getClosest(_, 5);
const closestTo = getClosest([4, 9, 15, 6, 2]);

24

Mã làm việc như dưới đây:

var array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];

function closest(array, num) {
  var i = 0;
  var minDiff = 1000;
  var ans;
  for (i in array) {
    var m = Math.abs(num - array[i]);
    if (m < minDiff) {
      minDiff = m;
      ans = array[i];
    }
  }
  return ans;
}
console.log(closest(array, 88));


8
Càng nhiều càng tốt.
Hot Licks

6
Tôi cho rằng đây là một giải pháp tốt hơn vì nó chỉ sử dụng JavaScript. Câu trả lời được chấp nhận sử dụng jQuery, không được đề cập trong câu hỏi ban đầu và những người khác đang xem câu hỏi này có thể không sử dụng.
Sean the Bean

17

Hoạt động với các mảng chưa được sắp xếp

Mặc dù có một số giải pháp tốt được đăng ở đây, JavaScript là một ngôn ngữ linh hoạt cung cấp cho chúng tôi các công cụ để giải quyết vấn đề theo nhiều cách khác nhau. Tất cả đều đến với phong cách của bạn, tất nhiên. Nếu mã của bạn có nhiều chức năng hơn, bạn sẽ thấy biến thể giảm phù hợp, nghĩa là:

  arr.reduce(function (prev, curr) {
    return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
  });

Tuy nhiên, một số có thể thấy rằng khó đọc, tùy thuộc vào phong cách mã hóa của họ. Vì vậy, tôi đề xuất một cách giải quyết vấn đề mới:

  var findClosest = function (x, arr) {
    var indexArr = arr.map(function(k) { return Math.abs(k - x) })
    var min = Math.min.apply(Math, indexArr)
    return arr[indexArr.indexOf(min)]
  }

  findClosest(80, [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]) // Outputs 82

Trái với các cách tiếp cận khác tìm giá trị tối thiểu bằng cách sử dụng Math.min.apply, cách này không yêu cầu arrsắp xếp mảng đầu vào . Chúng ta không cần quan tâm đến các chỉ mục hoặc sắp xếp nó trước.

Tôi sẽ giải thích từng dòng mã cho rõ ràng:

  1. arr.map(function(k) { return Math.abs(k - x) })Tạo một mảng mới, về cơ bản lưu trữ các giá trị tuyệt đối của các số đã cho (số trong arr) trừ đi số đầu vào ( x). Chúng tôi sẽ tìm số nhỏ nhất tiếp theo (cũng là số gần nhất với số đầu vào)
  2. Math.min.apply(Math, indexArr) Đây là một cách hợp pháp để tìm số nhỏ nhất trong mảng mà chúng ta vừa tạo trước đó (không có gì khác với nó)
  3. arr[indexArr.indexOf(min)]Đây có lẽ là phần thú vị nhất. Chúng tôi đã tìm thấy số nhỏ nhất của mình, nhưng chúng tôi không chắc mình nên cộng hay trừ số ban đầu ( x). Đó là bởi vì chúng tôi thường Math.abs()tìm thấy sự khác biệt. Tuy nhiên, array.maptạo (một cách hợp lý) một bản đồ của mảng đầu vào, giữ các chỉ mục ở cùng một vị trí. Do đó, để tìm ra số gần nhất, chúng ta chỉ cần trả về chỉ số của mức tối thiểu được tìm thấy trong mảng đã cho indexArr.indexOf(min).

Tôi đã tạo ra một thùng chứng minh nó.


1
Tôi không biết nhưng tôi đoán người ta có thể nghi ngờ về hiệu suất vì đây là thực tế 3nvà đó là ES5 mặc dù bạn trả lời vào năm 2016 và các giải pháp khác vẫn ổn ngay cả khi người này hỏi câu hỏi này rõ ràng không phải là lập trình viên vào thời điểm đó.
noob

1
Vâng, thật tuyệt khi thấy bạn học! Bằng cách này, tôi chỉ nói về những nghi ngờ về hiệu suất không cho rằng nó thực sự hoạt động kém hơn nhưng tôi đã chạy các con số cho bạn và O(n)giải pháp của bạn thực hiện ít hơn khoảng 100 nghìn ops / giây sau đó @paxdiablo O(log n)trên các số ngẫu nhiên. Khi thiết kế một thuật toán luôn luôn sắp xếp đầu tiên họ nói. (Ngoại trừ nếu bạn biết những gì bạn đang làm và bạn đã có điểm chuẩn để sao lưu.)
noob

1
Đạo cụ cho giải pháp đơn giản. Hoạt động tuyệt vời cho trường hợp sử dụng của tôi (Tôi không có sự sang trọng khi có một mảng được sắp xếp trước như noob.)
jaggedsoft

2
Bạn có thể làm cho findClosest trả về một hàm gọi lại giảm để làm cho nó có thể sử dụng lại trên tất cả các mảng: const findClosest = goal => (a,b) => Math.abs(a - goal) < Math.abs(b - goal) ? a : b;
Jakob E

1
Ví dụ: [2, 42, 82, 122, 162, 202, 242, 282, 322, 362].reduce(findClosest(80))
Jakob E

11

Đối với các mảng được sắp xếp (tìm kiếm tuyến tính)

Tất cả các câu trả lời cho đến nay tập trung vào việc tìm kiếm trong toàn bộ mảng. Xem xét mảng của bạn đã được sắp xếp và bạn thực sự chỉ muốn số gần nhất, đây có lẽ là giải pháp nhanh nhất:

var a = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
var target = 90000;

/**
 * Returns the closest number from a sorted array.
 **/
function closest(arr, target) {
  if (!(arr) || arr.length == 0)
    return null;
  if (arr.length == 1)
    return arr[0];

  for (var i = 1; i < arr.length; i++) {
    // As soon as a number bigger than target is found, return the previous or current
    // number depending on which has smaller difference to the target.
    if (arr[i] > target) {
      var p = arr[i - 1];
      var c = arr[i]
      return Math.abs(p - target) < Math.abs(c - target) ? p : c;
    }
  }
  // No number in array is bigger so return the last.
  return arr[arr.length - 1];
}

// Trying it out
console.log(closest(a, target));

Lưu ý rằng thuật toán có thể được cải thiện rất nhiều, ví dụ như sử dụng cây nhị phân.


Trong khi chiến lược này ở đây là tốt, điều này có một số lỗi chính tả. Ví dụ, a[i]hoặc i[0].
Wesley

1
Cảm ơn, @WesleyWorkman. Chỉ cần sửa chúng. Tôi hy vọng tôi có tất cả. Nhân tiện, bạn cũng có thể chỉnh sửa câu trả lời của người khác.
Hubert Grzeskowiak

Tôi cần chỉnh sửa ở đâu để trả lời mã ở trên để có giá trị gần nhất cao hơn? Ví dụ: [110, 111, 120, 140, 148, 149, 155, 177, 188, 190] Nếu tôi tìm kiếm 150, tôi sẽ nhận được 155 chứ không phải 149. Tôi đã thử nhưng gặp khó khăn trong việc giải quyết điều này. Bạn có thể giúp. Cảm ơn
dùng1199842

9

Tất cả các giải pháp được thiết kế quá mức.

Nó đơn giản như:

const needle = 5;
const haystack = [1, 2, 3, 4, 5, 6, 7, 8, 9];

haystack.sort((a, b) => {
  return Math.abs(a - needle) - Math.abs(b - needle);
});

// 5

1
Thật vậy, nhiều hơn đến mức. nhưng để "lấy số gần nhất ra khỏi mảng", bạn vẫn phải chọn phần tử đầu tiên từ mảng đã sắp xếp.
Shaya Ulman

6

Giải pháp này sử dụng bộ định lượng tồn tại ES5 Array#some, cho phép dừng lặp, nếu một điều kiện được đáp ứng.

Đối lập với Array#reduce, nó không cần lặp lại tất cả các yếu tố cho một kết quả.

Trong cuộc gọi lại, một deltagiá trị tuyệt đối giữa giá trị tìm kiếm và thực tếitem được lấy và so sánh với delta cuối cùng. Nếu lớn hơn hoặc bằng nhau, việc lặp lại dừng lại, bởi vì tất cả các giá trị khác với đồng bằng của chúng đều lớn hơn giá trị thực.

Nếu deltatrong cuộc gọi lại nhỏ hơn, thì mục thực tế được gán cho kết quả và deltađược lưu vào lastDelta.

Cuối cùng, các giá trị nhỏ hơn với đồng bằng bằng nhau được lấy, như trong ví dụ dưới đây 22, kết quả là 2.

Nếu có mức độ ưu tiên của các giá trị lớn hơn, kiểm tra delta phải được thay đổi từ:

if (delta >= lastDelta) {

đến:

if (delta > lastDelta) {
//       ^^^ without equal sign

Điều này sẽ nhận được với 22, kết quả 42(Ưu tiên của các giá trị lớn hơn).

Hàm này cần các giá trị được sắp xếp trong mảng.


Mã có mức độ ưu tiên của các giá trị nhỏ hơn:

function closestValue(array, value) {
    var result,
        lastDelta;

    array.some(function (item) {
        var delta = Math.abs(value - item);
        if (delta >= lastDelta) {
            return true;
        }
        result = item;
        lastDelta = delta;
    });
    return result;
}

var data = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];

console.log(21, closestValue(data, 21)); // 2
console.log(22, closestValue(data, 22)); // 2  smaller value
console.log(23, closestValue(data, 23)); // 42
console.log(80, closestValue(data, 80)); // 82

Mã có mức độ ưu tiên cao hơn:

function closestValue(array, value) {
    var result,
        lastDelta;

    array.some(function (item) {
        var delta = Math.abs(value - item);
        if (delta > lastDelta) {
            return true;
        }
        result = item;
        lastDelta = delta;
    });
    return result;
}

var data = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];

console.log(21, closestValue(data, 21)); //  2
console.log(22, closestValue(data, 22)); // 42 greater value
console.log(23, closestValue(data, 23)); // 42
console.log(80, closestValue(data, 80)); // 82


Vì vậy, bạn cho rằng mảng đã cho được sắp xếp ... Điều đó giúp bạn tiết kiệm rất nhiều thời gian.
Redu

1
Mảng của op có vẻ được sắp xếp, nên có :)
Nina Scholz

Giải pháp đầu tiên phá vỡ các đầu vào có cùng số hai lần. ví dụclosestValue([ 2, 2, 42, 80 ], 50) === 2
Sébastien Vercammen

@ SébastienVercammen, dữ liệu của op là duy nhất và được sắp xếp.
Nina Scholz

@NinaScholz OP chỉ xác định "Tôi có một mảng có số trong đó""Tôi muốn số tôi đã thay đổi thành số gần nhất của mảng" . Mảng ví dụ chỉ là một ví dụ. Một mảng không đảm bảo các mục duy nhất.
Sébastien Vercammen

4

ES6

Hoạt động với các mảng được sắp xếp và chưa sắp xếp

Số nguyên và số nổi, Chuỗi được hoan nghênh

/**
 * Finds the nearest value in an array of numbers.
 * Example: nearestValue(array, 42)
 * 
 * @param {Array<number>} arr
 * @param {number} val the ideal value for which the nearest or equal should be found
 */
const nearestValue = (arr, val) => arr.reduce((p, n) => (Math.abs(p) > Math.abs(n - val) ? n - val : p), Infinity) + val

Ví dụ:

let values = [1,2,3,4,5]
console.log(nearestValue(values, 10)) // --> 5
console.log(nearestValue(values, 0)) // --> 1
console.log(nearestValue(values, 2.5)) // --> 2

values = [100,5,90,56]
console.log(nearestValue(values, 42)) // --> 56

values = ['100','5','90','56']
console.log(nearestValue(values, 42)) // --> 56

3

Tôi không biết liệu tôi có nên trả lời một câu hỏi cũ không, nhưng vì bài đăng này xuất hiện đầu tiên trên các tìm kiếm của Google, tôi hy vọng rằng bạn sẽ tha thứ cho tôi khi thêm giải pháp của tôi & 2c của tôi vào đây.

Vì lười biếng, tôi không thể tin rằng giải pháp cho câu hỏi này sẽ là LOOP, vì vậy tôi đã tìm kiếm thêm một chút và quay lại với chức năng lọc :

var myArray = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
var myValue = 80;

function BiggerThan(inArray) {
  return inArray > myValue;
}

var arrBiggerElements = myArray.filter(BiggerThan);
var nextElement = Math.min.apply(null, arrBiggerElements);
alert(nextElement);

Đó là tất cả !


1
Vì vậy, những gì về giới hạn dưới? Bạn luôn sử dụng giá trị cao hơn tiếp theo. Nhưng cách tiếp cận của bạn làm tôi nhớ goog.math.clamp(đóng cửa google) chỉ với các mảng và không quan tâm đến giới hạn dưới.
noob

Giải pháp của bạn trả về số cao hơn tiếp theo từ mảng. Không có giá trị gần nhất và chính xác được tìm thấy.
Hubert Grzeskowiak

2

Câu trả lời của tôi cho một câu hỏi tương tự là kế toán cho các mối quan hệ và nó là trong Javascript đơn giản, mặc dù nó không sử dụng tìm kiếm nhị phân nên nó là O (N) chứ không phải O (logN):

var searchArray= [0, 30, 60, 90];
var element= 33;

function findClosest(array,elem){
    var minDelta = null;
    var minIndex = null;
    for (var i = 0 ; i<array.length; i++){
        var delta = Math.abs(array[i]-elem);
        if (minDelta == null || delta < minDelta){
            minDelta = delta;
            minIndex = i;
        }
        //if it is a tie return an array of both values
        else if (delta == minDelta) {
            return [array[minIndex],array[i]];
        }//if it has already found the closest value
        else {
            return array[i-1];
        }

    }
    return array[minIndex];
}
var closest = findClosest(searchArray,element);

https://stackoverflow.com/a/26429528/986160


2

Tôi thích cách tiếp cận từ Fusion, nhưng có một lỗi nhỏ trong đó. Như thế là đúng:

    function closest(array, number) {
        var num = 0;
        for (var i = array.length - 1; i >= 0; i--) {
            if(Math.abs(number - array[i]) < Math.abs(number - array[num])){
                num = i;
            }
        }
        return array[num];
    }

Nó cũng nhanh hơn một chút vì nó sử dụng forvòng lặp cải tiến .

Cuối cùng, tôi đã viết chức năng của mình như thế này:

    var getClosest = function(number, array) {
        var current = array[0];
        var difference = Math.abs(number - current);
        var index = array.length;
        while (index--) {
            var newDifference = Math.abs(number - array[index]);
            if (newDifference < difference) {
                difference = newDifference;
                current = array[index];
            }
        }
        return current;
    };

Tôi đã thử nghiệm nó console.time()và nó hơi nhanh hơn các chức năng khác.


Hey, bạn có thể giải thích tại sao nó là một improved for loop? Vòng lặp đảo ngược không phải lúc nào cũng là một cải tiến hiệu suất.
A1rPun

Bạn .lengthchỉ đánh giá một lần, khi bạn khai báo i, trong khi đối với vòng lặp này. Nhưng tôi nghĩ var i = arr.length;while (i--) {}sẽ còn nhanh hơn nữa
Jon

Tôi cập nhật câu trả lời của tôi. Tôi đã thay đổi nó thành while. Bây giờ nó thậm chí còn nhanh hơn.
Jon

0

Một tìm kiếm nhị phân sửa đổi một chút trên mảng sẽ hoạt động.


3
Trời ạ, thật kỳ quái - dường như ai đó không thích tìm kiếm nhị phân. (Thậm chí nghĩ rằng đó là giải pháp chung tốt nhất.)
Hot Licks

0

Đối với phạm vi nhỏ, điều đơn giản nhất là có một mảng bản đồ, trong đó, ví dụ, mục thứ 80 sẽ có giá trị 82 trong đó, để sử dụng ví dụ của bạn. Đối với một phạm vi rộng hơn, thưa thớt hơn, có lẽ cách để đi là tìm kiếm nhị phân.

Với ngôn ngữ truy vấn, bạn có thể truy vấn các giá trị ở một số khoảng cách hai bên của số đầu vào của bạn và sau đó sắp xếp qua danh sách rút gọn. Nhưng SQL không có khái niệm tốt về "tiếp theo" hoặc "trước đó", để cung cấp cho bạn một giải pháp "sạch".


0

Một biến thể khác ở đây chúng ta có phạm vi vòng tròn nối từ đầu đến chân và chỉ chấp nhận giá trị tối thiểu cho đầu vào đã cho. Điều này đã giúp tôi có được các giá trị mã char cho một trong các thuật toán mã hóa.

function closestNumberInCircularRange(codes, charCode) {
  return codes.reduce((p_code, c_code)=>{
    if(((Math.abs(p_code-charCode) > Math.abs(c_code-charCode)) || p_code > charCode) && c_code < charCode){
      return c_code;
    }else if(p_code < charCode){
      return p_code;
    }else if(p_code > charCode && c_code > charCode){
      return Math.max.apply(Math, [p_code, c_code]);
    }
    return p_code;
  });
}

0
#include <algorithm>
#include <iostream>
#include <cmath>

using namespace std;

class CompareFunctor
{

public:
    CompareFunctor(int n) { _n = n; }
    bool operator()(int & val1, int & val2)
    {
        int diff1 = abs(val1 - _n);
        int diff2 = abs(val2 - _n);
        return (diff1 < diff2);
    }

private:
    int _n;
};

int Find_Closest_Value(int nums[], int size, int n)
{
    CompareFunctor cf(n);
    int cn = *min_element(nums, nums + size, cf);
    return cn;
}

int main()
{
    int nums[] = { 2, 42, 82, 122, 162, 202, 242, 282, 322, 362 };
    int size = sizeof(nums) / sizeof(int);
    int n = 80;
    int cn = Find_Closest_Value(nums, size, n);
    cout << "\nClosest value = " << cn << endl;
    cin.get();
}

0

Hiệu quả nhất sẽ là một tìm kiếm nhị phân. Tuy nhiên, ngay cả các giải pháp đơn giản cũng có thể thoát khi số tiếp theo khớp với số hiện tại . Gần như tất cả các giải pháp ở đây không tính đến việc mảng được sắp xếp và lặp đi lặp lại mặc dù toàn bộ điều: /

const closest = (orderedArray, value, valueGetter = item => item) =>
  orderedArray.find((item, i) =>
    i === orderedArray.length - 1 ||
    Math.abs(value - valueGetter(item)) < Math.abs(value - valueGetter(orderedArray[i + 1])));

var data = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];

console.log('21 -> 2', closest(data, 21) === 2);
console.log('22 -> 42', closest(data, 22) === 42); // equidistant between 2 and 42, select highest
console.log('23 -> 42', closest(data, 23) === 42);
console.log('80 -> 82', closest(data, 80) === 82);

Điều này có thể được chạy trên phi nguyên thủy quá, vd closest(data, 21, item => item.age)

Thay đổi findđể findIndextrả về chỉ mục trong mảng.


Điều gì về mảng không có thứ tự?
EdG

Đối với không có thứ tự, hãy lấy một trong những giải pháp không thoát, tuy nhiên nếu bạn đang thực hiện công việc nhiều lần thì có thể tối ưu hơn để sắp xếp mảng một lần. Như đã đề cập nếu mảng thực sự lớn thì tìm kiếm nhị phân sẽ hiệu quả hơn so với tìm kiếm tuyến tính.
Đaminh

0

Để tìm hai số gần nhất trong mảng

function findTwoClosest(givenList, goal) {
  var first;
  var second;
  var finalCollection = [givenList[0], givenList[1]];
  givenList.forEach((item, firtIndex) => {
    first = item;

    for (let i = firtIndex + 1; i < givenList.length; i++) {
      second = givenList[i];

      if (first + second < goal) {
        if (first + second > finalCollection[0] + finalCollection[1]) {
          finalCollection = [first, second];
        }
      }
    }
  });

  return finalCollection;
}

var counts = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
var goal = 80;
console.log(findTwoClosest(counts, goal));

-5

Đây là đoạn mã để tìm phần tử gần nhất với một số từ một mảng trong Độ phức tạp O (nlog (n)): -

Đầu vào: - {1,60,0, -10,100,87,56} Phần tử: - 56 Số gần nhất trong mảng: - 60

Mã nguồn (Java):

package com.algo.closestnumberinarray;
import java.util.TreeMap;


public class Find_Closest_Number_In_Array {

    public static void main(String arsg[]) {
        int array[] = { 1, 60, 0, -10, 100, 87, 69 };
        int number = 56;
        int num = getClosestNumber(array, number);
        System.out.println("Number is=" + num);
    }

    public static int getClosestNumber(int[] array, int number) {
        int diff[] = new int[array.length];

        TreeMap<Integer, Integer> keyVal = new TreeMap<Integer, Integer>();
        for (int i = 0; i < array.length; i++) {

            if (array[i] > number) {
                diff[i] = array[i] - number;
                keyVal.put(diff[i], array[i]);
            } else {
                diff[i] = number - array[i];
                keyVal.put(diff[i], array[i]);
            }

        }

        int closestKey = keyVal.firstKey();
        int closestVal = keyVal.get(closestKey);

        return closestVal;
    }
}

Bài đăng yêu cầu javascript trong thẻ
Shannon Hochkins
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.