“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”
一、题目描述
给定一个链表的头结点 head,判断链表删除一个节点后是否可以成为回文链表。若可以则返回 true;否则返回 false。
注意:输入用例均保证链表长度 大于等于 3
输入:
head = [1,2,2,3,1]
输出:
true
输入:head = [5,1,8,8,1,5]
输出:true
输入:head = [1,2,3,4]
输出:false
二、思路分析
本题在判断是否可以形成回文链表时,可以将链表转换为切片进行判断。
判断切片 slic 在删除一个元素后是否为回文时,可以假设删除掉 slic[i] 之后,切片的 slic[:i] 和 slic[len(slic)-i:] 是否对称,并且切片 slic[i+1:len(slic)-i] 是否为回文,即可判断在删除掉 slic[i] 之后,切片 slic 是否为回文;
同理,亦可以对称的删除 slic[len(slic)-1-i] 处的元素,判断切片 slic 是否为回文。
两种情况,仅需满足一种即可说明原链表可以形成回文链表
例如样例中的链表:
我们首先找到两端对称的元素为1和1,
之后我们可以选择删除 slic[1] 或 slic[3],我们发现当删除 slic[3] 时可将原链表变成一个回文链表,则原链表可以形成回文链表。
代码
func isPalindrome(head *ListNode) bool {
temp := make([]int, 0)
for head != nil {
temp = append(temp, head.Val)
head = head.Next
}
i, j := 0, len(temp)
for i <= j && temp[i] == temp[j] {
i++
j--
}
//原链表本身即为回文链表
//原链表本身不是回文链表时,删除时的两种情况
return i >= j || slicIsPalindrome(temp[i:j]) || slicIsPalindrome(temp[i+1:j+1])
}
func slicIsPalindrome(slic []int) bool {
for i := 0; i < len(slic)/2; i++ {
if slic[i] != slic[len(slic)-1-i] {
return false
}
}
return true
}
总结
本题主要考察了对于数组的操作,在使用索引操作数组时应认真的思考索引应该怎么写,注意在使用索引截取部分数组时区间为左闭右开。本题对于本身就是回文链表的判断是直接通过左右索引的大小来进行判断,当做索引大于等于右索引时即可说明原链表为回文链表,所以在删除时仅需对链表中间的元素 slic[len(slic)/2] 进行删除即可。