【力扣竞赛题解】第 97 场双周赛

79 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情

分割数组中数字的数位

题目大意:给你一个字符串数组,把每个字符串拆分成字符数组,并拼接在一起返回

模拟

题目比较明确了,按照题意模拟即可

package main

import "strconv"

func separateDigits(nums []int) []int {
	ans := make([]int, 0)
	for i := 0; i < len(nums); i++ {
		s := strconv.Itoa(nums[i])
		for j := 0; j < len(s); j++ {
			ans = append(ans, int(s[j]-'0'))
		}
	}
	return ans
}

从一个范围内选择最多整数 I

题目大意:给你一个数组,你从1到n最多选(不能选数组里的数)几个数,使得和不超过k。

贪心

想要选的最多,就是优先选小的即可,从1开始枚举,如果不在数组里就选上,和大于k就停止。

package main

func maxCount(banned []int, n int, maxSum int) int {
	ans := 0
	m := make(map[int]bool)
	for _, num := range banned {
		m[num] = true
	}
	for i := 1; i <= n; i++ {
		if maxSum < i {
			break
		}
		if !m[i] {
			maxSum -= i
			ans++
		}
	}
	return ans
}
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

两个线段获得的最多奖品

题意:在一个坐标轴上有一些奖品,你可以取两个长度为k的区间,奖品个数和最大为多少

贪心

我们可以利用双指针求一个长度为k的最大和,对于两个区间,我们分情况讨论

  • 两区间有交集,相当于一个长度为2k的区间
  • 无交集,双指针枚举第二个区间的右端点,第二个区间值+左端点左边的一个区间的最大值
package main

import "fmt"

type pos struct {
	idx       int
	value     int
	maxk_left int
	sumk_left int
	left      int
}

func getLeft(poss []*pos, right, k int) int {
	l, r := 0, right
	//fmt.Println("get", right, k, right-k)
	for l < r {
		mid := (l + r) / 2
		if poss[mid].idx < poss[right].idx-k {
			l = mid + 1
		} else {
			r = mid
		}
	}
	//fmt.Println("get ans", l, poss[l].idx, right-k)
	return l
}

func maximizeWin(prizePositions []int, k int) int {
	poss := make([]*pos, 0)
	for i := 0; i < len(prizePositions); i++ {
		if len(poss) == 0 {
			poss = append(poss, &pos{idx: prizePositions[i], value: 1})
		} else {
			if poss[len(poss)-1].idx == prizePositions[i] {
				poss[len(poss)-1].value++
			} else {
				poss = append(poss, &pos{idx: prizePositions[i], value: 1})
			}
		}
	}
	summ := make([]int, len(poss))

	// 前缀和
	summ[0] = poss[0].value
	for i := 1; i < len(poss); i++ {
		summ[i] = summ[i-1] + poss[i].value
	}
	// 有交集时 2k

	ans := 0

	for i := 0; i < len(poss); i++ {
		l := getLeft(poss, i, 2*k)
		if l == 0 {
			ans = max(ans, summ[i])
		} else {
			ans = max(ans, summ[i]-summ[l-1])
		}
	}
	fmt.Println(1, ans)

	// 无交集时

	tmp := 0
	for i := 0; i < len(poss); i++ {
		l := getLeft(poss, i, k)
		//fmt.Println(i, l, poss[i].idx, poss[l].idx, k)
		poss[i].left = l
		if l == 0 {
			tmp = max(tmp, summ[i])
			poss[i].sumk_left = summ[i]
		} else {
			tmp = max(tmp, summ[i]-summ[l-1])
			poss[i].sumk_left = summ[i] - summ[l-1]
		}
		poss[i].maxk_left = tmp
	}

	// 贪心

	for i := 1; i < len(poss); i++ {

		if poss[i].left > 0 {
			ans = max(ans, poss[poss[i].left-1].maxk_left+poss[i].sumk_left)
			fmt.Println("-1", i, poss[i].left)
		}
	}
	fmt.Println(2, ans)
	//fmt.Println(summ)
	return ans

}

func max(a, b int) int {
	if a < b {
		return b
	}
	return a
}

二进制矩阵中翻转最多一次使路径不连通

题意:给你01二维矩阵,问将一个1变为0是否可以使左上角与右下角不连通。 没想明白,嘎了