IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【力扣hot100】day2 -> 正文阅读

[数据结构与算法]【力扣hot100】day2

今天继续整理hot100题。

目录

10、有效的括号

题目内容

题解

11、合并两个有序链表

题目内容

题解

12、括号生成

题目内容

题解

13、下一个排列

题目内容

题解

13、最长有效括号

题目内容

题解

14、搜索旋转排序数组

题目内容

题解

15、在排序数组中查找元素的第一个和最后一个位置

题目内容

题解

16、组合总和

题目内容

题解

17、全排列

题目内容

题解

?

18、旋转图像

题目内容

题解

19、字母异位词分组

题目内容

题解

20、最大子数组和

题目内容

题解


10、有效的括号

题目内容

给定一个只包括 '(',')','{','}','[',']'?的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
?

示例 1:

输入:s = "()"
输出:true


示例?2:

输入:s = "()[]{}"
输出:true


示例?3:

输入:s = "(]"
输出:false

题解

一般思路,栈顶元素匹配即可。?

/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function (s) {
  const arr = [];
  for (let i = 0; i < s.length; i++) {
    switch (s[i]) {
      case "(":
        arr.push(s[i]);
        break;
      case "{":
        arr.push(s[i]);
        break;
      case "[":
        arr.push(s[i]);
        break;
      case ")":
        if (arr.pop() !== "(") {
          return false;
        }
        break;
      case "}":
        if (arr.pop() !== "{") {
          return false;
        }
        break;
      case "]":
        if (arr.pop() !== "[") {
          return false;
        }
        break;
      default:
        return false;
    }
  }
  if (arr.length > 0) {
    return false;
  }
  return true;
};

11、合并两个有序链表

题目内容

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。?

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]


示例 2:

输入:l1 = [], l2 = []
输出:[]


示例 3:

输入:l1 = [], l2 = [0]
输出:[0]
?

题解

一般思路,直接按照顺序遍历添加即可。?

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} list1
 * @param {ListNode} list2
 * @return {ListNode}
 */
var mergeTwoLists = function (list1, list2) {
  if (!list1) {
    return list2;
  }
  if (!list2) {
    return list1;
  }
  let res = null;
  if (list1.val <= list2.val) {
    res = list1;
    list1 = list1.next;
  } else {
    res = list2;
    list2 = list2.next;
  }
  let pos = res;
  while (list1 && list2) {
    if (list1.val <= list2.val) {
      pos.next = list1;
      list1 = list1.next;
    } else {
      pos.next = list2;
      list2 = list2.next;
    }
    pos = pos.next;
  }
  if (list1) {
    pos.next = list1;
  }
  if (list2) {
    pos.next = list2;
  }
  return res;
};

12、括号生成

题目内容

数字 n?代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:

输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]


示例 2:

输入:n = 1
输出:["()"]
?

题解

容易观察到,如果想得到匹配的字符串,左括号的数量一定要>=右括号的数量,那么递归解决即可。注意边界条件,left和right最多是等于0,绝不能小于0。而等于0时,一定要返回一个包含空字符串的数组,这个是最根本的字符串,否则将无法得到任何一个字符串。

/**
 * @param {number} n
 * @return {string[]}
 */
var generateParenthesis = function (n) {
  return getStrings(n, n);
};

// 传入左括号和右括号的个数
function getStrings(left, right) {
  let arr = [];
  if (left < 0 || right < 0) {
    return arr;
  }
  if (left === right) {
    if (left === 0) {
      arr.push("");
    } else {
      // 此时只能放入左括号
      let sub = getStrings(left - 1, right);
      arr = arr.concat(sub.map((item) => "(" + item));
    }
  } else if (left < right) {
    // 此时可以放入左括号,也可以放入右括号
    let sub1 = getStrings(left - 1, right);
    arr = arr.concat(sub1.map((item) => "(" + item));
    let sub2 = getStrings(left, right - 1);
    arr = arr.concat(sub2.map((item) => ")" + item));
  }
  return arr;
}

13、下一个排列

题目内容

整数数组的一个 排列??就是将其所有成员以序列或线性顺序排列。

例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。
整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。

例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。
给你一个整数数组 nums ,找出 nums 的下一个排列。

必须 原地 修改,只允许使用额外常数空间。

示例 1:

输入:nums = [1,2,3]
输出:[1,3,2]


示例 2:

输入:nums = [3,2,1]
输出:[1,2,3]


示例 3:

输入:nums = [1,1,5]
输出:[1,5,1]
?

题解

这道题需要仔细观察规律,花费了我一定的时间。我的具体思路如下:

首先研究一下什么叫按字典顺序排列。简单来说,就是让整个数字最小限度地增大,就是下一个排列。

因此,如果最后两位是升序的数字,直接交换它们,就可以得到下一个排列。

否则,说明从后往前是先变大,直到达到一个转折点,在转折点之前是从后往前递减的。如果这个转折点是0,说明,整个数组就是从前往后递减的,那么直接反转数组即可。

如果转折点不是0,说明我们可以根据转折点前后的数字做一些文章。如果想要让数字变大,由于转折点及其后面的数字都是从前往后递减的,交换它们并不能使数字变大。所以,我们考虑,转折点前面的第一个数字p,和,转折点及其后面的数字。在转折点及其后面的数字中,从后往前,找到第一个比p大的数字q,q一定是比p大且最小的数字。

然后,p和q交换位置,这样数字就一定会变大。要想使变动最小,则需要把q后面所有数字按照升序排列,拼接在q的后面即可。这样得到的,就是正确的答案。

注意,力扣不支持数组的concat方法,所以只能使用push(...ls)。

/**
 * @param {number[]} nums
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var nextPermutation = function (nums) {
  // 12345 < 12354 < 12435 < 12453 < 12534 < 12543 < 13245 < 13254 < 13425
  // 考察最后两位
  let n = nums.length;
  if (nums[n - 2] < nums[n - 1]) {
    // 如果最后两位是升序,则直接交换即可
    let temp = nums[n - 1];
    nums[n - 1] = nums[n - 2];
    nums[n - 2] = temp;
  } else {
    // 否则,说明最后两位是降序
    // 需要找到第一个转折点
    let i = n - 2;
    while (i >= 0 && nums[i] >= nums[i + 1]) {
      i--;
    }
    if (i < 0) {
      // 说明整个数组都是降序,直接倒过来成升序即可
      nums.reverse();
    } else {
      // 找到第一个转折点是i+1处
      // 应该把从后往前数,第一个比nums[i]大的放在nums[i]处,其余的升序放在后面
      let j = n - 1;
      while (j >= i + 1 && nums[j] <= nums[i]) {
        j--;
      }
      let temp = nums[j];
      nums[j] = nums[i];
      nums[i] = temp;
      // i后面的升序排列
      let tempList = nums.slice(i + 1, n);
      tempList.sort((a, b) => a - b);
      nums.splice(i + 1);
      nums.push(...tempList);
    }
  }
};

官方思路更加高效,有兴趣可以去看看。?

13、最长有效括号

题目内容

给你一个只包含 '('?和 ')'?的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:

输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"


示例 2:

输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"


示例 3:

输入:s = ""
输出:0
?

题解

这道题很难!!!

一开始,我是想使用类似map记录前n项和的方法来解,但是发现无法控制字符串中间的内容是否合法。后来仔细想了想,可以使用动态规划。

具体思路就是,用数组arr记录以第i个字符结尾,符合条件的最长子串。从前往后判断,如果是左括号或者第一个字符,则arr[i]记为0。如果是有括号,再分两种情况:

如果第i-1个字符是左括号,那么直接令arr[i]=arr[i-2]+2,因为这样就可以把前面的衔接上了。当然,如果i-2<0,arr[i]=2。

如果第i-1个字符是右括号,这样思考。到第i-1个字符,它应该组成了arr[i-1]这么长的子串。我们需要越过这些字符:从第i-1个字符往前推arr[i-1]个字符,这样就可以跳过以第i-1个字符结尾的字符串,看前面的字符是否能够与第i个字符配对。这个字符就是第i-1-arr[i-1]个字符,如果它是左括号,那么就可以跟第i个字符组成长度为arr[i-1]+2的合法字符串。那么,arr[i]=arr[i-1-arr[i-1]-1]+arr[i-1]+2。

在这里要注意边界情况。如果i-1-arr[i-1]<0,或者i-1-arr[i-1]处是右括号,说明没有左括号与第i个字符配对,所以arr[i]=0。或者,如果i-1-arr[i-1]-1<0,那么说明第i-1-arr[i-1]个字符就是第一个字符,那么arr[i]就直接等于arr[i-1]+2。

/**
 * @param {string} s
 * @return {number}
 */
var longestValidParentheses = function (s) {
  // 动态规划
  let n = s.length;
  // 以第i个字符结尾的最长子串长度
  const arr = new Array(n).fill(0);
  let res = 0;
  for (let i = 0; i < n; i++) {
    if (i === 0 || s[i] === "(") {
      arr[i] = 0;
    } else {
      if (s[i - 1] === "(") {
        arr[i] = i - 2 >= 0 ? arr[i - 2] + 2 : 2;
      } else {
        // 第i-1处是右括号,其组成的子串长度是arr[i-1]
        // 那么,要看i-1往左走arr[i-1]步的字符是不是左括号
        if (i - 1 - arr[i - 1] >= 0 && s[i - 1 - arr[i - 1]] === "(") {
          arr[i] =
            i - 1 - arr[i - 1] - 1 >= 0
              ? arr[i - 1 - arr[i - 1] - 1] + arr[i - 1] + 2
              : arr[i - 1] + 2;
        }
      }
    }
    res = Math.max(res, arr[i]);
  }
  return res;
};

14、搜索旋转排序数组

题目内容

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为?[4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回?-1?。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4


示例?2:

输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1


示例 3:

输入:nums = [1], target = 0
输出:-1
?

题解

说到底,这还是一个二分查找。只是需要分清楚,target和middle各在哪个部分,从而根据target和nums[middle]以及它们的位置去改变left和right的值。

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function (nums, target) {
  let n = nums.length;
  let left = 0,
    right = n - 1;
  // 看target在左半边还是右半边,左true右false
  let flag = target > nums[n - 1] ? true : false;
  while (left <= right) {
    let middle = parseInt((left + right) / 2);
    if (nums[middle] === target) {
      return middle;
    }
    if (flag) {
      // 在左半边
      if (nums[middle] < target) {
        // 如果nums[middle]比target小,那么middle可能在左半边,也可能在右半边
        if (nums[middle] <= nums[n - 1]) {
          // middle在右半边
          right = middle - 1;
        } else {
          // middle在左半边
          left = middle + 1;
        }
      } else {
        // 如果nums[middle]比target大,那么middle一定中左半边
        right = middle - 1;
      }
    } else {
      // 在右半边
      if (nums[middle] < target) {
        // 如果nums[middle]比target小,那么middle一定在右半边
        left = middle + 1;
      } else {
        // 如果nums[middle]比target大,那么middle可能在左半边,也可能在右半边
        if (nums[middle] <= nums[n - 1]) {
          // middle在右半边
          right = middle - 1;
        } else {
          // middle在左半边
          left = middle + 1;
        }
      }
    }
  }
  return -1;
};

15、在排序数组中查找元素的第一个和最后一个位置

题目内容

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回?[-1, -1]。

你必须设计并实现时间复杂度为?O(log n)?的算法解决此问题。

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]


示例?2:

输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]


示例 3:

输入:nums = [], target = 0
输出:[-1,-1]
?

题解

我的想法很粗暴,找到一个target的位置,往两边跑,找到所有target即可。。。

官方思路是先找第一个等于target的位置,再使用同样的算法找到第一个大于target的位置。有兴趣可以再试试。?

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var searchRange = function (nums, target) {
  let n = nums.length;
  let left = 0,
    right = n - 1;
  while (left <= right) {
    let middle = parseInt((left + right) / 2);
    if (nums[middle] === target) {
      let l = middle - 1,
        r = middle + 1;
      while (true) {
        if ((l < 0 || nums[l] !== target) && (r > n || nums[r] !== target)) {
          break;
        }
        if (l >= 0 && nums[l] === target) {
          l--;
        }
        if (r < n && nums[r] == target) {
          r++;
        }
      }
      return [l + 1, r - 1];
    } else if (nums[middle] < target) {
      left = middle + 1;
    } else {
      right = middle - 1;
    }
  }
  return [-1, -1];
};

16、组合总和

题目内容

给你一个 无重复元素 的整数数组?candidates 和一个目标整数?target?,找出?candidates?中可以使数字和为目标数?target 的 所有?不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。?

对于给定的输入,保证和为?target 的不同组合数少于 150 个。

示例?1:

输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。


示例?2:

输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]


示例 3:

输入: candidates = [2], target = 1
输出: []
?

题解

典型的完全背包组合问题,外层遍历candidates,内层升序遍历target即可。

我有个疑问在于,dp[i]=dp[i].concat(tempList)是成功的,但之前验证过,力扣有时候不支持concat方法,这里为什么又可以了?此外,dp[i].push(...tempList)的结果是错的,为什么呢?它与concat理论上应该是一致的才对呀????

/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum = function (candidates, target) {
  // 完全背包问题,组合问题
  // 外层循环nums,内层升序遍历target
  let dp = new Array(target + 1).fill([]);
  dp[0] = [[]];
  for (let candidate of candidates) {
    for (let i = 1; i <= target; i++) {
      if (i >= candidate) {
        let tempList = JSON.parse(JSON.stringify(dp[i - candidate]));
        tempList = tempList.map((item) => {
          item.push(candidate);
          return item;
        });
        // dp[i].push(...tempList);
        dp[i] = dp[i].concat(tempList);
      }
    }
  }
  return dp[target];
};

17、全排列

题目内容

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]


示例 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]


示例 3:

输入:nums = [1]
输出:[[1]]
?

题解

一直想写一下全排列算法,直到今天遇到了这道题。

我的思路就是,使用递归,每次取一个还没有取过的数字。这就需要,使用一个数组visited来记录是否取过该位置的数字,还要使用step记录这次递归是取第几个数字。当step===nums.length时,说明取到最后一个数字,只需要把没有取过的那个数字放入结果数组,返回即可。

否则,说明不是最后一个数字。那么,先找出所有没取过的数字们,记为raw。依次取raw中的数字,记为当前数字,并在visited中标记该数字已经取过,然后递归进行第step+1次调用。这样,得到子数组,然后在子数组的每个数组最前面,加入当前数字。再把刚刚标记过的当前数字置为没有取过,再取下一个当前数字即可。

最终,通过递归,得到了正确答案。

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var permute = function (nums) {
  const n = nums.length;
  // 是否取过该数字
  let visited = new Array(n).fill(false);
  return getRes(nums, visited, 1);
};

// 取第step个数字
function getRes(nums, visited, step) {
  let res = [];
  if (step === nums.length) {
    // 取最后一个数字
    let pos = visited.findIndex((item) => !item);
    res.push([nums[pos]]);
    return res;
  }
  // 找到还没有取过的数字
  let raw = [];
  for (let i = 0; i < visited.length; i++) {
    if (!visited[i]) {
      raw.push(i);
    }
  }
  for (let pos of raw) {
    visited[pos] = true;
    let subRes = getRes(nums, visited, step + 1);
    let temp = subRes.map((item) => {
      item.unshift(nums[pos]);
      return item;
    });
    res = res.concat(temp);
    visited[pos] = false;
  }
  return res;
}

?

18、旋转图像

题目内容

给定一个 n?×?n 的二维矩阵?matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例 1:

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]


示例 2:

输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

题解

这道题不是很难,只需要找到前后数组的映射关系即可。

/**
 * @param {number[][]} matrix
 * @return {void} Do not return anything, modify matrix in-place instead.
 */
var rotate = function (matrix) {
  const copy = JSON.parse(JSON.stringify(matrix));
  const n = matrix.length;
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      matrix[i][j] = copy[n - 1 - j][i];
    }
  }
};

19、字母异位词分组

题目内容

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。

示例 1:

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]


示例 2:

输入: strs = [""]
输出: [[""]]


示例 3:

输入: strs = ["a"]
输出: [["a"]]

题解

这道题我没有什么好办法。官方题解给出了两种思路:第一个是对每个字符串进行排序,把排序结果相同的放入同一个集合里面,这个比较简单,不必多说。

第二个是,记录每个字符串中,26个字母出现的次数,存为长度26的数组。此时,JavaScript语言特性帮了大忙(在题解后面细说)。若把一个数组作为普通Object对象的键,那么会先调用这个数组的toString方法,形成一个字符串,然后作为键,存入对象。只有两个完全相同的数组的toString才是完全相同的,因此,使用数组作为对象的键可以保证唯一性!

这样就可以,把符合某数组的字符串存入该数组对应的集合中,最终直接返回对象的values即可。

这道题告诉我们,优秀的语言特性及其原理是很重要的!

/**
 * @param {string[]} strs
 * @return {string[][]}
 */
var groupAnagrams = function (strs) {
  // 统计每个字符串中,每个字母出现的次数,保存在长度为26的数组中
  // 记录每种出现次数对应的字符串
  const map = {};
  for (let str of strs) {
    const arr = new Array(26).fill(0);
    for (let i = 0; i < str.length; i++) {
      arr[str[i].charCodeAt() - "a".charCodeAt()]++;
    }
    if (map[arr]) {
      map[arr].push(str);
    } else {
      map[arr] = [str];
    }
  }
  return Object.values(map);
};

这里说一下为什么数组可以作为对象的键。

我们知道,JavaScript的普通Object对象的键,只能是字符串或Symbol。因此,其他类型作为键的时候,都会转化为字符串。比如obj={a:1},实际上是obj={'a':1}。同样,其他类型作为键会是这样:

const arr1 = [1, 2],
  arr2 = [1, 2];
const map = {};
map[arr1] = 1;
function f1() {}
function f2() {}
map[f1] = 2;
map[f2] = 3;
const obj = { a: 1 };
map[obj] = 4;
console.log(Object.keys(map));
// [ '1,2', 'function f1() {}', 'function f2() {}', '[object Object]' ]

对于数组、函数和Object对象,作为对象的键时,都会先调用自己的toString转化成字符串。?不同的数组和函数,toString的结果都不一样,因此具有唯一性。但Object对象,其toString结果都是'[object Object]',因此,不论使用多少个Object对象作为键,都是操作'[object Object]'这个字符串的。

20、最大子数组和

题目内容

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组?[4,-1,2,1] 的和最大,为?6 。


示例 2:

输入:nums = [1]
输出:1


示例 3:

输入:nums = [5,4,-1,7,8]
输出:23

题解

最基础的动态规划了,没什么可说的。?

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function (nums) {
  let n = nums.length;
  // 到第i个数字为止,最大连续数组和
  const arr = new Array(n).fill(0);
  let res = -Infinity;
  for (let i = 0; i < n; i++) {
    if (i === 0) {
      arr[0] = nums[0];
    } else {
      if (arr[i - 1] >= 0) {
        arr[i] = nums[i] + arr[i - 1];
      } else {
        arr[i] = nums[i];
      }
    }
    res = Math.max(res, arr[i]);
  }
  return res;
};
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 02:14:52  更:2022-09-15 02:15:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 17:28:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码