算法--Week1

这篇博客涵盖了三个编程挑战:将罗马数字转化为整数,解决两数之和问题,以及判断一个整数是否为回文。在罗马数字转换中,通过遍历字符串并应用特殊规则来计算数值。两数之和问题通过双指针遍历数组找到目标和的组合。回文数检测则通过比较数字的前半部分与反转后的后半部分来确定。这些题目涉及基础算法和数据处理技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简单:

1.罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/roman-to-integer
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的代码:

func romanToInt(s string) int {
/*
思路:从罗马数字第一位开始依次扫描,如果后一位大于前一位,则count-=value,反之,count+=value

*/
	var symbols = map[byte]int{'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}//利用map建立每个罗马数字与数字的映射
        var count int//最后要得出的整数
		var a int//罗马数字的位数
	    a=len(s)
		for i:=0;i<=a-1;i++{
			value:=symbols[s[i]]//暂存当前位的罗马数字的数值
			if i<=(a-2)&&value<symbols[s[i+1]] {
				count-=value//后一位大于前一位
			}else {
				count+=value//前一位大于后一位
			}
		}
  return count
}

func main() {
fmt.Println(romanToInt("XIV"))
}

运算截图:
在这里插入图片描述
在这里插入图片描述
解题过程中出现的错误:
“if i<=(a-2)&&value<symbols[s[i+1]] {”这一行错写成了“if i<=(a-1)&&value<symbols[s[i+1]] {”导致报错“panic: runtime error: index out of range [3] with length 3在这里插入图片描述
。原因是最高位是a-1,if循环应该在a-2时停止。否则会溢出。
2.两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:将数组里的每个数x枚举,寻找数组中是否有target-x,已经匹配过的x就不用再匹配了。而每一个元素不能被使用两次,所以我们只需要在 x 后面的元素中寻找 target - x。
代码:

func twoSum(nums []int,target int) []int {
	m:=len(nums)
	kong:=[]int{}
	for  i:=0;i<=m;i++ {
		for j:=i+1;j<=m-1;j++{
			if nums[i]+nums[j]==target {
				kong=append(kong,i,j)
				return kong
			}
		}
	}

	return kong
}

func main() {
var a []int=make([]int,4,6)
a[0]=2
a[1]=7
a[2]=11
a[3]=15
fmt.Println(twoSum(a,9))
}

运行截图:
在这里插入图片描述
提交截图:
在这里插入图片描述

3.回文数
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。

回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

例如,121 是回文,而 123 不是。
思路:将数字本身反转,然后将反转后的数字与原始数字进行比较,如果它们是相同的,那么这个数字就是回文。
但是,如果反转后的数字大于 \text{int.MAX}int.MAX,我们将遇到整数溢出问题。

按照第二个想法,为了避免数字反转可能导致的溢出问题,为什么不考虑只反转 \text{int}int 数字的一半?毕竟,如果该数字是回文,其后半部分反转后应该与原始数字的前半部分相同。

func isPalindrom(x int)  bool{
	var m bool
	a:=0
	for i:=x;i>0;i/=10{
		a=a*10+i%10
	}
	if a==x {
		m=true
	}else {
		m=false
	}
	return m
}

运行结果:在这里插入图片描述
提交截图:
在这里插入图片描述

示例 1:

输入:x = 121
输出:true

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、中等

1.整数翻转
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。

示例 1:

输入:x = 123
输出:321

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-integer
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码:

func Reverse(x int) int {
	var reverse int//定义最后的翻转数
	for x!=0 {
		if reverse < math.MinInt32/10 || reverse > math.MaxInt32/10 {
			return 0
		}//根据题目要求x必须为二进制
		end:=x%10//end是每次x除以10后的余数,乘以10就相当于进一位,每乘一次进一位,这样就可以将位数翻转
		x/=10//x=x/10,与前面的x!=0对应,每次都把个位数去掉,慢慢将这个数除尽
		reverse=reverse*10+end//将每次的end和10倍的reverse相加所得到的数为最后的翻转数
	}
	return reverse//将最后的翻转数返回
}

运行结果:
在这里插入图片描述

提交截图:
在这里插入图片描述
2.适合打劫的日子
你和一群强盗准备打劫银行。给你一个下标从 0 开始的整数数组 security ,其中 security[i] 是第 i 天执勤警卫的数量。日子从 0 开始编号。同时给你一个整数 time 。

如果第 i 天满足以下所有条件,我们称它为一个适合打劫银行的日子:

第 i 天前和后都分别至少有 time 天。
第 i 天前连续 time 天警卫数目都是非递增的。
第 i 天后连续 time 天警卫数目都是非递减的。
更正式的,第 i 天是一个合适打劫银行的日子当且仅当:security[i - time] >= security[i - time + 1] >= … >= security[i] <= … <= security[i + time - 1] <= security[i + time].

请你返回一个数组,包含 所有 适合打劫银行的日子(下标从 0 开始)。返回的日子可以 任意 顺序排列。

示例 1:

输入:security = [5,3,3,3,5,6,2], time = 2
输出:[2,3]
解释:
第 2 天,我们有 security[0] >= security[1] >= security[2] <= security[3] <= security[4] 。
第 3 天,我们有 security[1] >= security[2] >= security[3] <= security[4] <= security[5] 。
没有其他日子符合这个条件,所以日子 2 和 3 是适合打劫银行的日子

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-good-days-to-rob-the-bank
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:题目中第 ii 天适合打劫需满足:第 ii 天前连续 \textit{time}time 天警卫数目都是非递增与第 ii 天后连续 \textit{time}time 天警卫数目都是非递减。只需要预先计算出第 ii 天前警卫数目连续非递增的天数以及第 ii 天后警卫数目连续非递减的天数即可判断第 ii 天是否适合打劫。设第 ii 天前警卫数目连续非递增的天数为left [i],第 ii 天后警卫数目连续非递减的天数为right [i] ,当第 ii 天同时满足 left [i] ≥time,right [i​]≥time 时,即可认定第 ii 天适合打劫。
代码:

	var a []int = make([]int, 7, 10)
	a[0]=5
	a[1]=3
	a[2]=3
	a[3]=3
	a[4]=5
	a[5]=6
	a[6]=2
	fmt.Println(goodDaysToRobBank(a,2))

}
func goodDaysToRobBank(security []int, time int) []int {
	var ans []int//这个数组是存放最后结果的
	n := len(security)
	left := make([]int, n)//左边非递减的天数
	right := make([]int, n)//右边非递增的天数
	for i := 1; i < n; i++ {
		if security[i] <= security[i-1] {
			left[i] = left[i-1] + 1
		}//计算左边非递减的天数
		if security[n-i-1] <= security[n-i] {
			right[n-i-1] = right[n-i] + 1
		}//计算右边非递增的天数
	}

	for i := time; i < n-time; i++ {
		if left[i] >= time && right[i] >= time {
			ans = append(ans, i)//将符合要求的天数加入到ans中
		}
	}
	return ans
}

运行结果:
在这里插入图片描述
提交结果:在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值