程序员面试金典(01.09/02.01)字符串轮转/移除重复节点

01.09 字符串轮转。给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成(比如,waterbottle是erbottlewat旋转后的字符串)。

示例1:

 输入:s1 = "waterbottle", s2 = "erbottlewat"
 输出:True
示例2:

 输入:s1 = "aa", s2 = "aba"
 输出:False
提示:

字符串长度在[0, 100000]范围内。
说明:

你能只调用一次检查子串的方法吗?

思路:暴力方法很麻烦,可以使用KMP算法.

KMP算法简介:

KMP算法的作用是在一个已知字符串中查找子串的位置,也叫做串的模式匹配。

当我们判断两个字符串是否匹配时,首先想到的是两层循环,挨个遍历。但是很麻烦,最好的时间复杂度是O(n),最坏的时间复杂度是O(m*n)。而空间复杂度是O(1),不消耗空间,消耗时间。

那么KMP算法的主要思想就是以空间换时间。我们可以减少回溯的次数。

这里可以有更加详细的讲解视频:最浅显易懂的 KMP 算法讲解_哔哩哔哩_bilibili

 

 当我们碰到不相同的时候可以避免在子串中重复寻找。

 这里会有一个next数组来对比较过的重复字符串进行一个记录。

 KMP算法的实现代码

 KMP中存储的next数组。

有一个思想:两个原来的字符串拼接在一起一定会包含改变后的字符串。(无论怎么旋转)

class Solution {
    public boolean isFlipedString(String s1, String s2) {
        //字符串匹配  --->KMP算法 避免重复的字符串挨个进行比较 两个原来的字符串拼接在一起一定会包含改变后的字符串。
        return s1.length()==s2.length() && (s1+s1).contains(s2);
    }
}

02.01移除重复节点:编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。

示例1:

 输入:[1, 2, 3, 3, 2, 1]
 输出:[1, 2, 3]
示例2:

 输入:[1, 1, 1, 1, 2]
 输出:[1, 2]
提示:

链表长度在[0, 20000]范围内。
链表元素在[0, 20000]范围内。
进阶:

如果不得使用临时缓冲区,该怎么解决?

单链表

数据结构中,在单链表的开始结点之前附设一个类型相同的结点,称之为头结点。头结点的数据域可以不存储任何信息,头结点的指针域存储指向开始结点的指针(即第一个元素结点的存储位置)。
含有头结点的链表插入
作用
1、防止单链表是空的而设的,当链表为空的时候,带头结点的头指针就指向头结点,如果当链表为空的时候,单链表没有带头结点,那么它的头指针就为NULL。
2、是为了方便单链表的特殊操作,能有效减少代码量,在插入在表头或者删除第一个结点时不用考虑特殊情况,删除或插入用户的第一个节点的值和删除或插入中间的值用一样的代码,这样就保持了单链表操作的统一性!
3、单链表加上头结点之后,无论单链表是否为空,头指针始终指向头结点,因此空表和非空表的处理也统一了,方便了单链表的操作,也减少了程序的复杂性和出现bug的机会。
4、总结来说,没有头结点对第一个结点的操作大多和中间结点不太一样,每个操作都要考虑特殊情况,有头结点的话就不必考虑那么多了,还不容易出现代码错误。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeDuplicateNodes(ListNode head) {
        if(head ==null){//防止出现空的情况
            return head;
        }
        Set<Integer> set =new HashSet<Integer>();
        ListNode list=head;//慢指针  双指针
        set.add(head.val);//先将数据加入set集合中
        while(list.next!=null){
            ListNode list1=list.next;//快指针
            if(set.add(list1.val)){
                list=list.next;  //返回list相当于指向了最后一个
            }else{
                list.next=list.next.next;
            }     
        }
        list.next=null;
        return head;
    }
}

 List1.val能加到set集合中:

 List1.val不能加到set集合中:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值