30 15. 3Sum 三数之和细节描述

97 阅读1分钟

15. 3Sum

对于复杂数据,先进行数据整理排序,再进行相关问题解,往往是明智之举

解题思路

  1. 首先通过从大到小的排序后,容易发现如果数字大于 target则直接返回 results
  2. 输出的是元素不能重复的,所以通过从大到小的排序后,如果发现 nums[i] === nums[i - 1]则进行跳过
  3. 取两个指针,一个 start = i + 1 end = num.length - 1,去首尾遍历剩下的数据
  4. 如果 nums[i] + nums[start] + nums[end]等于 target 则 push 进 results,那么需要对数据进行去重操作,即start部分去重 while (nums[start] === nums[start + 1]) start++ end部分进行去重 while (nums[end] === nums[end - 1]) end--
  5. 如果小于目标值,则去重后 start++
  6. 如果大于目标值,则去重后 end--

代码

function threeSum(nums) {
	const results = []

	// 数组小于3,直接返回
	if (nums.length < 3) return results

	
	// 从小到大排序
	nums = nums.sort((a, b) => a - b)
        
    // 设置相加后的目标值
	let target = 0

	for (let i = 0; i < nums.length - 2; i++) {
		// 如果大于目标值,直接跳出循环
		if (nums[i] > target) break

		// 相同的元素直接跳过
		if (i > 0 && nums[i] === nums[i - 1]) continue

		
		// 剩下的数据首部
		let start = i + 1

		// 剩下的数据尾部
		let end = nums.length - 1
		
		while (start < end) {
			let sum = nums[i] + nums[start] + nums[end]

			if (sum === target) {
				// 存储找到的值
				results.push([nums[i], nums[start], nums[end]])

			    // 排除重复的值
				while (nums[start] === nums[start + 1]) start++
				while (nums[end] === nums[end - 1]) end--

				// 排除重复的值后,说明start,end停留再最有一个重复的目标值,需要再进行一次移动
				start++
				end--

			// 小于说明  start的位置取值太小
			} else if (sum < target) {
                                while (nums[start] === nums[start + 1]) start++
				start++

			// 大于的话,说明 end位置取值太大
			} else { // (sum > target)
                                while (nums[end] === nums[end - 1]) end--
				end--
			}
		}
	}

	return results
};