数组相关算法题

Posted by violetks on April 4, 2021

第一题:旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
例如输入数组[1, 2, 3, 4, 5],将它变成旋转数组比如[3, 4, 5, 1, 3]或者[4, 5, 1, 2, 3]。
输入一个非递减排序的数组,将它进行旋转,求旋转数组的最小值。
NOTE:给出的所有元素都大于0,若数组大小为 0,请返回 0。

// 示例1
输入:[3, 4, 5, 1, 2]
返回:1
// 示例2
输入:[3, 100, 200, 3]
返回:3

方法一:先将数组从小到大排序,arr[0]即为最小值。可以使用JavaScript中的sort()函数排序。sort()参数是一个比较函数,如果没有参数是按照各个字符的 Unicode 编码排序。

// 当没有参数传入时,默认按照数组转成字符串后的结果每一位的 Unicode 编码进行排序
let arr = [311, 43, 54, 4, 40, 26, 31, 33];
arr.sort();
console.log(arr); // [26, 31, 311, 33, 4, 40, 43, 54]
function minNumberInRotateArray (rotateArray) {
  if (rotateArray.length === 0) return 0;
  function compare (value1, value2) {
    return value1 > value2 ? 1 : 0;
  }
  rotateArray.sort(compare);
  return rotateArray[0];
}

问题:关于比较函数的返回值规则如下:
(1)返回结果小于 0,则 value1、value2 顺序不变。
(2)返回结果等于 0,则 value1、value2 顺序不变。
(3)返回结果大于 0,则 value1、value2 交换位置。
相当于返回值结果大于 0 时才会交换位置,否则顺序不变。也就是返回值可能出现的情况只有两种,是否可以用布尔值代替呢?比如上面的比较函数可以改写如下,测试通过也没问题。

function compare (value1, value2) {
  return value1 > value2;
}

方法二:使用 Math.min()

function minNumberInRotateArray (rotateArray) {
  return rotateArray.length === 0 ? 0 : Math.min(...rotateArray);
}

第二题:二维数组中的查找

在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

[
  [1, 2, 8, 9],
  [2, 4, 9, 12],
  [4, 7, 10, 13],
  [6, 8, 11, 15]
]

一、Java 实现
(1)遍历数组,如果找到就返回 true

public class Solution {
  public boolean Find(int target, int [][] array) {
    for (int i = 0; i < array.length; i++) {
      for (int j = 0; j < array[0].length; j++) {
        if (array[i][j] == target) {
          return true;
        }
      }
    }
    return false;
  }
}

(2)从二维数组左下角开始找:利用每行每列递增的特点,target 大于当前值,向右移动 j++;target 小于当前值,向上移动 i–

public class Solution {
  public boolean Find(int target, int [][] array) {
    int rows = array.length;
    if (rows == 0) {
      return false;
    }
    int cols = array[0].length;
    if (cols == 0) {
      return false;
    }
    // 左下
    int row = rows - 1; // 起始行号
    int col = 0; // 起始列号
    while (row >= 0 && col < cols) {
      if (array[row][col] < target) {
        col++;
      } else if (array[row][col] > target) {
        row--;
      } else {
        return true;
      }
    }
    return false;
  }
}

二、JavaScript 实现

// 从左下找
function Find (target, array) {
  if (!target || !array || array.length === 0 || array[0].length === 0) {
    return false;
  }
  let row = array.length - 1; // 起始行号
  let col = 0; // 起始列号
  while (row >= 0 && col < array[0].length) {
    if (array[row][col] < target) {
      col++;
    } else if (array[row][col] > target) {
      row--;
    } else {
      return true;
    }
  }
  return false;
}

第三题:计算最大收益

某人连续几天的股票涨跌情况用一数组表示,计算卖出后能获得的最大收益。

// 示例1
输入:[1, 6, 4, 3, 5]
返回:5
因为第一天是 1,第二天是 6,可获最大收益是 5
// 示例2
输入:[7, 6, 5, 4, 3, 2]
返回:0
因为一直在下降,可获最大收益是 0
function getFullProfit (arr) {
  var count = 0;

  arr.forEach((i, arr) => {
    if (arr[i] > arr[i+1]) {
      count++;
    }
  })
  if (count === arr.length-1) {
    return 0;
  } else {
    var max = Math.max(...arr);
    var min = Math.min(...arr);
    var res = max - min;
    return res;
  }
}

第四题:对象数组去重

// 示例1
输入:[{a:1,b:'vio'},{a:2,b:'asd'},{a:3,b:'zxc'},{a:1,b:'vio'},{a:4,b:'efg'}]
返回:[{a:1,b:'vio'},{a:2,b:'asd'},{a:3,b:'zxc'},{a:4,b:'efg'}]

方法一:使用 reduce() 方法

function unique (arr) {
  let obj = {};
  arr = arr.reduce((pre, cur) => {
      obj[cur.a] ? ' ' : obj[cur.a] = true && pre.push(cur)
      return pre;
  }, [])
  return arr;
}

reduce 的语法: array.reduce(callback, [initialValue])
initialValue是 callback 初次调用时的第一个参数值。
callback函数的四个参数:

1. previousValue 上一次调用回调返回的值或者是提供的初始值initialValue))
2. currentValue 数组中当前被处理的元素
3. index 当前元素在数组中的索引
4. array 调用 reduce 的数组

方法二:判断对象中是否存在某个 key

function unique (arr) {
  var res = [];
  var obj = {};
  arr.forEach((item, index) => {
    if (!obj[arr[index].a]) {
      res.push(arr[index]);
      obj[arr[index].a] = true;
    }
  })
  return res;
}