[leetcode笔记003]数组之移除元素移除元素

知识点

  • 双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组,指向当前要处理的元素
  • 慢指针:指向更新 新数组下标的位置,即下一个将要赋值的位置
  • 不必拘泥指针是指向首部还是末尾,比较灵活
  • 思路:暴力解法需要两遍for循环时,考虑双指针
  • 时间复杂度O(n),空间复杂度O(1)
27. 移除元素
  • 我的方法,在数组尾部放了一个指针,这个方法的优缺点:优点最坏两个指针合起来也只需遍历一次,避免了需要保留的元素的重复赋值操作。,缺点是相对位置变了
  • 快慢指针法优缺点:优点相对位置未改变,缺点重复赋值和最坏两个指针都要遍历一遍。
var removeElement = function(nums, val) {
	let i
	let j = nums.length-1
	let temp
	for ( i = 0; i <= j; i++ ){
		if ( nums[i] === val ) {
			//复习了下splice的用法
			//nums.splice( i, 1, ums[j])
			temp = nums[i]
			nums[i] = nums[j]
			nums[j] = temp
			j--
			i--
		}
	}
	return nums[j] === val ? i+1 : j+1
};
  • 快慢指针法:
var removeElement = function(nums, val) {
	let i
	let j = 0
	for ( i = 0; i < nums.length; i++ ){
		if ( nums[i] !== val ) {
			nums[j] =  nums[i]
			j++
		}
	}
	return j
};
26. 删除有序数组中的重复项
var removeDuplicates = function(nums) {
	let fast
	let slow = 0
	if (nums.length === 1) {
		return 1
	}
	for ( fast = 0; fast < nums.length; fast++ ) {
		if (nums[fast] !== nums[slow]) {
			slow++
			nums[slow] = nums[fast]
		}
	}
	return slow + 1
};
283. 移动零
var moveZeroes = function(nums) {
	let fast
	let slow = 0
	for (fast = 0; fast < nums.length; fast++) {
		if(nums[fast] !== 0) {
		nums[slow] = nums[fast]
		slow++
		}
	}
	for (slow; slow <nums.length; slow++) {
		nums[slow] = 0
	}
	return nums
};
844. 比较含退格的字符串
  • 官方的方法一用了栈,虽然空间复杂度不符合,但是一个思路
  • 官方的方法二,非常棒的思路,因为普通字符只受后面的#约束,所以从末尾开始遍历并记录#的数量,契合空间复杂度
  • 我的方法,还是覆盖,缺点还是操作数多,而且如果转数组的操作空间复杂度>O(1),则我的方法也不符合空间复杂度
var backspaceCompare = function(s, t) {
	let fast= 0
	let s_slow = 0
	let t_slow = 0
	//先转化为数组
	s = s.split("")
	t = t.split("")  

	for ( ; fast<s.length; fast++) {
		if (s[fast] !== "#"){
		// s是字符串时,这样的修改是无效的
			s[s_slow] = s[fast]
			s_slow++
		} else {
			s_slow === 0 ? 0 : s_slow--
		}
	}
	for (fast = 0; fast < t.length; fast++) {
		if (t[fast] !== "#"){
			t[t_slow] = t[fast]
			t_slow++
		} else {
			t_slow === 0 ? 0 : t_slow--
		}
	}

	// 上面俩应该可以写成一个函数,懒,不写了
	//转化回字符串
	s = s.toString()
	t = t.toString()

	// 复习下slice(start,end),不包括end
	// 注意此处是字符串,可以这么比较,但如果是数组则不能使用 == 和 === 需要逐个比较
	return (s_slow === t_slow) && (s.slice(0, s_slow) == t.slice(0, t_slow))
};
977. 有序数组的平方
var sortedSquares = function(nums) {
	let left = 0
	let right = nums.length - 1
	let numsRes = [...nums]
	let rightRes = right  
	while ( left <= right) {
		if (Math.abs(nums[left]) <= Math.abs(nums[right])) {
			numsRes[rightRes] = nums[right] * nums[right]
			right --
		} else {
			numsRes[rightRes] = nums[left] * nums[left]
			left ++
		}
		rightRes --
	}
	return numsRes
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述:给定一个非负整数数组nums和一个整数m,你需要将这个数组分成m个非空的连续子数组。设计一个算法使得这m个子数组中的最大和最小。 解题思路: 这是一个典型的二分搜索题目,可以使用二分查找来解决。 1. 首先确定二分的左右边界。左边界为数组中最大的值,右边界为数组中所有元素之和。 2. 在二分搜索的过程中,计算出分割数组的组数count,需要使用当前的中间值来进行判断。若当前的中间值不够分割成m个子数组,则说明mid值偏小,将左边界更新为mid+1;否则,说明mid值偏大,将右边界更新为mid。 3. 当左边界小于等于右边界时,循环终止,此时的左边界即为所求的结果。 具体步骤: 1. 遍历数组,找到数组中的最大值,并计算数组的总和。 2. 利用二分查找搜索左右边界,从左边界到右边界中间的值为mid。 3. 判断当前的mid值是否满足题目要求,若满足则更新右边界为mid-1; 4. 否则,更新左边界为mid+1。 5. 当左边界大于右边界时,循环终止,返回左边界即为所求的结果。 代码实现: ```python class Solution: def splitArray(self, nums: List[int], m: int) -> int: left = max(nums) right = sum(nums) while left <= right: mid = (left + right) // 2 count = 1 total = 0 for num in nums: total += num if total > mid: total = num count += 1 if count > m: left = mid + 1 else: right = mid - 1 return left ``` 时间复杂度分析:二分搜索的时间复杂度为O(logN),其中N为数组的总和,而遍历数组的时间复杂度为O(N),因此总的时间复杂度为O(NlogN)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值