Как проверить, содержит ли больший массив определенный меньший массив?

1

Для домашней работы мне нужно написать программу, которая принимает два параметра, которые представляют собой массивы натуральных чисел, дополненные защитой (0).

Программа должна проверить, присутствует ли последовательность элементов (без 0), содержащихся во втором массиве, где-либо в первом массиве. Если это так, то программа возвращает индекс элемента, с которого первый массив начинает последовательность элементов, содержащихся во втором массиве. Если такой последовательности нет, программа возвращает -1. Если таких последовательностей несколько, он должен вернуть индекс первой из найденных последовательностей (с наименьшим индексом).

Примеры:

-> find([2, 4, 6, 8, 10, 12, 0], [6, 8, 0])

-> 2

-> find([2, 4, 6, 8, 10, 12, 0], [10, 12, 14, 0])

-> -1

Теперь я написал код, который частично работает, но не проходит все тесты.

function find(tab1, tab2){
    var index = [];
    var num=0;
    for(var i=0;tab2[i]!=0;i++){
        for(var j=0;tab1[j]!=0;j++){
            if(tab2[i]==tab1[j]){
                index[num] = j;
                num++;
                break;
            }
        }
    }
    if(index.length == tab2.length-1){
    return index[0];
    }
    else{
        return -1;
    }
}

По сути, я не знаю, является ли этот разрыв правильным добавлением, поскольку я не уверен, как он работает в JavaScript (что делает цикл разрывом).

  • 0
    Перерыв выйдет из внутреннего цикла for. Затем выполнение продолжится со следующей итерации внешнего цикла for.
  • 0
    Я, например, считаю, что империтивный код выглядит некрасиво. Пища для размышлений: вы можете сделать это, используя редуктор или фильтр? Проверьте их на MDN (Google - ваш друг). Я бы попытался разбить проблему и написать меньшие чистые функции. Это сделает ваш код декларативным. Вы должны применять принцип «Скажи, не спрашивай» (Google это).
Показать ещё 2 комментария
Теги:

3 ответа

1

Вы можете использовать вложенный цикл с временным индексом.

function find(source, needle) {
  for (var i = 0; source[i] != 0; i++) {
    var k = i;
    var j = 0;
    while (source[k] != 0 && needle[j] != 0) {
      if (source[k++] != needle[j++]) {
        break; // mismatch between source and needle 
      }
    }
    if (needle[j] == 0) {
      return i; // full match with entire needle
    }
  }
  return -1;
}

var res = find([ 1, 7, 8, 2, 3, 4, 5, 0], [2, 3, 4, 0]);
console.log(res);
0

Я бы также рекомендовал немного переработать ваш подход... в настоящее время вы проверяете ваше подмножество по всему вашему набору, что противоположно тому, что вы хотите. Вы хотите пройтись по всему набору, сравнить заданное значение с первым значением подмножества, а затем выполнить цикл, чтобы проверить остальные значения на соответствие. Это подход, который я бы порекомендовал:

var fullSet = [1, 6, 37, 54, 3, 87, 37, 15, 9, 21, 53];
var subSet1 = [37, 15, 9];
var subSet2 = [37, 54, 3];
var subSet3 = [3, 90, 512];

function find(full, sub) {
  //Loop entire fullset
  for(var i = 0; i < full.length; i++) {
    //Current fullset value and first subset value match
    if(full[i] == sub[0]) {
      var matches = true; //Toggle for if entire subset does not match
      //Loop through subset
      for(var j = 0; j < sub.length; j++) {
        //Check current full set value against subset value
      	if(full[i + j] != sub[j]) {
          matches = false;
          break;
        } 
      }
      //It managed to last the entire subset without finding a mismatch
      //We can thus safely return the current fullset index
      if(matches) {
        return i;
      }
    }
  }
  //Return -1 if no matches found
  return -1;
}

console.log(find(fullSet, subSet1));
console.log(find(fullSet, subSet2));
console.log(find(fullSet, subSet3));
0

break в JavaScript

завершает текущий оператор цикла, переключателя или метки и передает управление программой в оператор, следующий за завершенным оператором.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break

Теперь то, что вы хотите сделать, - это каждая позиция в первом массиве, проверить, начинается ли второй массив в этой позиции (и он полностью содержится). Если да, вуаля! Вы можете вернуть этот индекс как результат, потому что это наименьший индекс, который содержит массив (если бы он не был наименьшим, вы бы нашли его раньше).

function find(tab1, tab2) {
  for(var i = 0; tab1[i] != 0; i++) {
    if( canIFindSecondArrayStartingAtPosition(tab1, tab2, i) ) {
      return i;
    }
  }

  // if you haven't returned yet it means that tab2 was not found!
  return -1;
}

Теперь, как вы реализуете функцию canIFindSecondArrayStartingAtPosition?

Вы хотите посетить каждую позицию во втором массиве и проверить, является ли число в этой позиции числом в первом массиве в той же позиции + начальный индекс. Если нет, то второй массив не может быть найден, и вы можете немедленно вернуть false.

В конце, если вы смогли перебрать весь второй массив (и найти все числа), вы возвращаете true.

Попробуйте реализовать это, не глядя на мой код:

Таким образом, все решение будет выглядеть так.

function canIFindSecondArrayStartingAtPosition(tab1, tab2, initialPosition) {
    for(var i=0; tab2[i]!=0; i++) {
      if( tab2[i] != tab1[i + initialPosition] ) {
        return false;
      }
    }

    return true;
}

function find(tab1, tab2) {
  for(var i = 0; tab1[i] != 0; i++) {
    if( canIFindSecondArrayStartingAtPosition(tab1, tab2, i) ) {
      return i;
    }
  }

  // if you haven't returned yet it means that tab2 was not found!
  return -1;
}

var res = find([ 1, 7, 8, 2, 3, 4, 5, 0], [2, 3, 4, 0]);
console.log(res);

res = find([2, 4, 6, 8, 10, 12, 0], [10, 12, 14, 0]);
console.log(res);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню