【问题标题】:Can't find a solution for array reverse algorithm problem找不到数组反向算法问题的解决方案
【发布时间】:2020-01-06 14:55:04
【问题描述】:

我有一个要求,我必须在不更改数组中“#”的索引的情况下反转数组,如下例所示:

  • 数组[18,-4,'#',0,8,'#',5]应该返回[5, 8, "#", 0, -4, "#", 18],这里的数字应该颠倒,不包括'#',同时保持相同的索引。

我已尝试获得正确的输出,但似乎并非在所有情况下都是正确的: var arr = [18,-4,'#',0,8,'#',5]; // 给出的结果是正确的 var arr1 = [18,-4,0,'#',8,'#',5]; // 结果不正确

var reverse = function(numbers, start, end){
	var temp = numbers[start];
  numbers[start] = numbers[end];
  numbers[end] = temp;
}
var flip = function(numbers) {
var start = 0;
var end = numbers.length-1;
	for(var i=0;i<parseInt(numbers.length/2);i++) {
  	if(numbers[i] === '#') {
    	start = i+1;
      end = numbers.length - i - i;
      reverse(numbers, start, end);
    } else if (numbers[numbers.length - i - 1] === '#') {
    	start = i;
      end = numbers.length - i - 2;
      reverse(numbers, start, end);
    } else {
    	reverse(numbers, start, end);
    }
  }
  return numbers;
}

var arr = [18,-4,'#',0,8,'#',5];
var arr1 = [18,-4,0,'#',8,'#',5];
console.log(flip(arr));
console.log(flip(arr1));

【问题讨论】:

    标签: javascript arrays algorithm reverse


    【解决方案1】:

    您可以简化函数并仅使用两个索引,即开始和结束,并检查索引处的值是否应该保留,然后选择另一个索引进行交换。

    const
        swap = (array, a, b) => [array[a], array[b]] = [array[b], array[a]],
        flip = numbers => {
            var start = 0,
                end = numbers.length - 1;
    
            while (start < end) {
                if (numbers[start] === '#') {
                    start++;
                    continue;
                }
                if (numbers[end] === '#') {
                    end--;
                    continue;
                }
                swap(numbers, start++, end--);
            }
            return numbers;
        },
        array1 = [18, -4, '#', 0, 8, '#', 5],
        array2 = [18, -4, 0, '#', 8, '#', 5];
    
    console.log(...flip(array1));
    console.log(...flip(array2));

    【讨论】:

      【解决方案2】:

      简单的方法是删除所有'#''s,使用内置的[].reverse 方法反转数组,然后重新插入'#''s:

      let flip = numbers => {
        let removed = numbers.reduce((r, v, i) =>
                v === '#' ? r.concat(i) : r
            , []);
      
        let reversed = numbers.filter(v => v !== '#').reverse();
      
        removed.forEach(i => reversed.splice(i, 0, '#'));
      
        return reversed;
      };
      
      let arr = [18, -4, '#', 0, 8, '#', 5];
      let arr1 = [18, -4, 0, '#', 8, '#', 5];
      console.log(flip(arr));
      console.log(flip(arr1));

      【讨论】:

      • 谢谢@junvar 的努力,但我需要它没有预定义的功能,我想使用循环的基本逻辑什么的,可以简化吗?
      • @SarveshMahajan:除非这是家庭作业,或者你有一些非常严重的性能限制,否则我建议使用filterconcatreduce 等可以使代码更易于阅读比自定义循环。
      【解决方案3】:

      你可以试试这个:

      var numbers = arr.filter(a => a !== '#')
      var revArr = [];
      arr.forEach((currentValue) => {
          if(currentValue !== "#") {
              revArr.push(numbers.pop());
          } else {
              revArr.push("#");
          }
      });
      
      

      【讨论】:

      • 感谢@sagar 的努力,不加过滤器可以简化吗?
      【解决方案4】:

      您可以将您的算法基于两个基本数组(反转数字数组和一个带有“#”保存位置的数组)

      const array = [5, 8, "#", 0, -4, "#", 18];
      
      function flip(array) {
      
        const arrayNumbers = array.filter((el, index) => el !== "#").reverse();
      
        var counter = 0;
      
        return array.map(el => el === "#").map(el => {
          if (!el) {
            let num = arrayNumbers[counter];
            counter = counter + 1;
            return num;
          } else {
            return "#"
          }
        })
      }
      
      console.log(flip(array));

      【讨论】:

      • 请注意,问题要求reverse,而不是sort
      • 感谢@G.aziz 的努力,但我需要在没有过滤器的情况下实现它,可以简化吗?
      • @SarveshMahajan:用自定义循环替换 filtermap 与简化相反。
      【解决方案5】:
      var arr = [18,-4,'#',0,8,'#',5]
      var stack = []
      
      for (i=0 ; i<arr.length; i++) {
          if (arr[i] == '#') continue;
          stack.push(arr[i]);
      }
      
      for (i=0 ; i<arr.length; i++) {
          if (arr[i] != '#') {
              arr[i] = stack.pop();
          }
      }
      
      console.log(arr)
      

      上面的代码应该可以解决你的问题。
      该实现使用堆栈,我们不断将元素插入堆栈,直到我们看到'#'并跳过它。 在创建输出数组时,我们将原始数组引用为“#”索引,并将堆栈引用为反向索引。

      【讨论】:

        【解决方案6】:

        你可以这样做。

                int end = v.length - 1;
                int start = 0;
                for (int i = 0; i < v.length >> 1; i++) {
                    if (v[start].equals("#")) {
                        start++;
                        continue;
                    }
                    if (v[end].equals("#")) {
                        end--;
                        continue;
                    }
                    Object temp = v[end];
                    v[end] = v[start];
                    v[start] = temp;
                    end--;
                    start++;
        
                }
                System.out.println(Arrays.toString(v));
        

        【讨论】:

        • 也许是现在,但不是更早。 OP更改了标签。
        猜你喜欢
        • 2023-04-10
        • 1970-01-01
        • 1970-01-01
        • 2021-11-30
        • 1970-01-01
        • 2021-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多