目录
题型:
1.删除有序数组中的重复项
要求:
给你一个 升序排列 的数组 nums
,请你原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
法一:
func removeDuplicates(nums []int) int {
//双指针解决法
left := 0
for right := 1; right < len(nums); right++ {
if nums[left] != nums[right] {
left = left + 1
nums[left] = nums[right]
}
}
return left + 1
}
/*因为是有序数组,所以在从左向右遍历过程中
1.若两指针指向的值相同,则左指针不变,右指针往右移一位。
2.若两指针指向的值不同,则将左指针往右移一位,右指针的值再赋给左指针
2.两数之和
要求:
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
func twoSum(nums []int, target int) []int {
//双指针法
var result []int
for left := 0; left < len(nums); left++ {
for right := left + 1; right < len(nums); right++ {
if nums[left]+nums[right] == target {
result = append(result, left, right)
}
}
}
return result
}
//左指针从第一位开始,右指针总比左指针多一位。
//左指针不动,右指针从左往右一直遍历,直至超出nums长度范围。
//接着左指针加1,右指针重复遍历。这个大循环直至超出nums长度范围。
//其中若左指向值+右指向值=target,则将左与右索引值写入定义的切片中
3.回文数
要求:
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。
//回文数
func isPalindrome(x int) bool {
/*法一
一.若该数等于0或该数小于0则不是回文数或尾数为0
二.通过获得,并且反转后半部分的数。
1.针对回文数的数量为偶数:后半部分反转后的数==前半部分的数则是回文数
2.针对回文数的数量为奇数:获得后半部分的数后,除去其中位数,若除取中位数后的数等于处理过后的原数,则这个数是中间数
*/
if x < 0 || (x%10 == 0 && x != 0) {
return false
}
reverseOfNum := 0
for x > reverseOfNum {
reverseOfNum = reverseOfNum*10 + x%10
x = x / 10
}
return x == reverseOfNum || x == reverseOfNum/10
//x==reverseOfNum 针对回文数数量为偶数,x==reverseOfNum/10 针对回文数数量为奇数(除以10是为了去除中位数)
}
4.罗马数字转整数
要求:
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 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。
给定一个罗马数字,将其转换成整数。
//罗马数字转整数
func romanToInt(s string) int {
var rouMaOfNum = map[byte]int{'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
n := len(s)
result := 0
for i := range s {
value := rouMaOfNum[s[i]]
if i < n-1 && value < rouMaOfNum[s[i+1]] {
result -= value
} else {
result += value
}
}
return result
}
5.最后一个单词长度
给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。
单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。
/*
先从尾部开始遍历
先排除空格
尾部空格排除完了,就可以通过index递减去遍历最后一个单词长度
*/
func lengthOfLastWord(s string) int {
index := len(s) - 1
for s[index] == ' ' {
index = index - 1
}
ans := 0
for index >= 0 && s[index] != ' ' {
ans++
index--
}
return ans
}
六.最长公共前缀
要求:
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
/*
1.先挑出开头两个进行比较
2.选出字符串最段的作为模板比较,然后返回两个字符串的公共前缀
3.然后接着以返回的公共字符串前缀与下一个字符再进行比较,再次返回公共前缀
*/
func longestCommonPrefix(strs []string) string {
count := len(strs)
prefix := strs[0]
for i := 1; i < count; i++ {
prefix = getPrefix(prefix, strs[i])
if prefix == "" {
break
}
}
return prefix
}
func getPrefix(str1 string, str2 string) string {
i := 0
length := min(len(str1), len(str2))
for i < length && str1[i] == str2[i] {
i++
}
return str1[:i]
}
func min(length1 int, length2 int) int {
if length1 > length2 {
return length2
} else {
return length1
}
}
七.搜索插入位置
要求:
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
/*
1.若已经存在了目标值,则直接返回索引值
2.若没有存在目标值,则可以从最后一位开始比较大小,
若比目标值大则往前移动,与前一位进行比较。
直至比较出比目标值小的值,则可以返回插入位置,这时候插入的位置应该为比它小的索引值的后面一位。
也就是代码中的 n+1。
*/
func searchInsert(nums []int, target int) int {
n := len(nums) - 1
for i := range nums {
if nums[i] == target {
return i
} else {
for n >= 0 && nums[n] > target {
n--
}
}
}
return n + 1
}
八.移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
//demo1
/*
通过快慢指针进行做题
这个是快指针从最后一位进行遍历值,若快指针指向的值与val值相同的则与慢指针的值进行交换。接着慢指针往前一位走。
快指针继续遍历,慢指针不动。这样若有与val值相同的都会与慢指针指向的值进行位置交换。
这样就可以将所有不同的值往前移,相同的值往后移了。
*/
func removeElement(nums []int, val int) int {
n := len(nums) - 1
fast, slow := n, n
for fast >= 0 {
if nums[fast] == val {
nums[fast], nums[slow] = nums[slow], nums[fast]
slow--
}
fast--
}
return slow + 1
}
//demo2
//这个执行更快!
/*
通过将不同于val的数字,重新写入切片nums中,
然后每次新添一个新值后,都将索引值加一,为下一个值的到来,准备好“位置”。
*/
func removeElement(nums []int, val int) int {
i := 0
for _, v := range nums {
if v != val {
nums[i] = v
i++
}
}
return i
}
九.爬楼梯
要求:
假设你正在爬楼梯。需要 n
阶你才能到达楼顶。
每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
//经典的动态规划题型
func climbStairs(n int) int {
p, q, r := 0, 0, 1
//动态规划
//递推公式:dp[i]=dp[i-1]+dp[i-2]
for i := 1; i <= n; i++ {
p = q
q = r
r = p + q
}
return r
}
keep....
注意:
1.字符串索引出来的值是byte类型
2.双指针有两种类型:相同方向进行遍历为快慢指针,相反方向进行遍历为对撞指针