初级算法(六)

这篇博客探讨了字符串的最长公共前缀问题,通过迭代找到数组中所有字符串的公共部分。此外,详细介绍了如何在单链表中删除特定节点和倒数第N个节点,以及两种不同的链表反转方法:一种使用栈,另一种使用双指针。这些算法均实现了高效的时间复杂度。
摘要由CSDN通过智能技术生成

初级算法(六)

1、引言

字符串
1、最长公共前缀:一个函数可以查找字符串数组中最长公共前缀,如果不存在则返回" "
单链表
1、删除链表中的某个节点
2、删除链表的倒数第N个节点
3、反转链表

2、最长公共前缀

​ 要知道公共最长前缀的定义,这个前缀的字符串最重要的是连续的。采取默认字符串数组中的第一个字符串为公共最长的前缀。然后对第一个字符串进行不断截取。

    /**
     *
     * @param strs 输入的字符串数组
     * @return 返回的最长公共前缀
     * 执行用时:0ms,内存消耗:39.2MB
     */
    public String longestCommonPrefix(String[] strs) {
     if(strs==null || strs.length==0)
         return "";
     //默认第一个为公共前缀
     String pre=strs[0];
     int i=1;
     while(i<strs.length){
         while(strs[i].indexOf(pre)!=0)
             //只要返回值是不是第一个就一直进行截取
             pre=pre.substring(0,pre.length()-1);
         i++;
     }
     return pre;
    }

3、删除链表中的某个节点

这个主要是看对于单链表的数据结构理解,单链表中的构成是一个数据域和指向下一个节点的指针。为此我们需要声明一个链表的对象。

public class ListNode{
    int val;//存的是数据
    ListNode next;//指向下一个节点的指针
    ListNode(){
    }
    ListNode(int val){
        this.val=val;
    }
    ListNode(int val,ListNode next){
        this.val=val;
        this.next=next;
    }
}

删除具体节点,需要首先将该节点相邻的节点的值赋值给该节点,并将指针变化为相邻节点的下一个指针。没有涉及任何算法。

    /**
     * 删除链表中的某个节点
     * @param node 被删除的节点,不能访问头节点
     *  执行用时:0ms,内存消耗:41MB
     */
    public void deleteNode(ListNode node) {
        ListNode nextNode = node.next;//node下的一个节点是nextNode节点。
        node.val=nextNode.val;
        node.next=nextNode.next;
    }

4、删除倒数第n个节点

这题首先需要计算单链表的长度,然后for循环遍历找到那个要删除的节点。这里我卡顿了一下,因为没弄懂Java的参数传递,Java的参数传递是值传递。就算是引用传递,参数传递则复制引用,因为改变了引用,所以原有的对象也会改变。这里调用length()方法,复制引用,但是其中的引用没有改变。因为单链表中的包含了next指针,指向下一个对象。

    /**
     *
     * @param head 单链表
     * @param n 倒数第n个节点
     * @return 删除后的单链表
     * 执行用时:0ms,内存消耗:39.4MB
     */
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode pre=head;
        int length=length(head);
        int last=length-n;
        if(last==0)
            return head.next;
        for (int i = 0; i <last-1 ; i++) {//找到要删除的节点的位置
            pre=pre.next;
        }
        pre.next=pre.next.next;
        return head;
    }
    int length(ListNode head){//这里是引用中的引用,引用中的引用改变了,其值还是不会改变,因为Java是值传递
        int length=0;
        while(head!=null){
            length++;
            head=head.next;
        }
        return length;
    }

5、反转链表

这题的一个解决办法,就是利用另外一个栈。利用栈的先进后出的原则。

    /**
     * 方法一:利用Java的栈结构的现金后出的原则
     * @param head
     * @return 反转后的单链表
     * 执行用时1ms,内存消耗41.5MB
     */
    public ListNode reverseList(ListNode head) {
        int l=length(head);
        if(l<=1)
            return head;
        Stack<ListNode> stack=new Stack<>();
        while(head!=null){
            stack.push(head);
            head=head.next;
        }
        ListNode node=stack.pop();//弹出尾节点
        ListNode dummy=node;//dummy则作为标记,标记新的单链表
        while(!stack.isEmpty()){
            ListNode tempNode=stack.pop();
            node.next=tempNode;
            node=node.next;
        }
        node.next=null;//将最后的尾节点的next的值设为null
        return dummy;
    }

还有一个解决办法就是使用双链表,但是这个双指针我没想到。

   /**
     * 方法2:双链表的求解
     * 将原链表的节点,作为新链表的头节点
     * @param head
     * @return 反转后的单链表
     *执行用时:0ms,内存消耗41.3MB
     */
    public ListNode reverseList2(ListNode head) {
        int l=length(head);
        if(l<=1)
            return head;
        ListNode node=null;
        while(head!=null){
            //先保存访问节点的下一个节点
            ListNode temp = head.next;
            //将新链表的节点挂在原始链表的后面
            head.next=node;
            //更新链表
            node=head;
            //重新赋值,继续访问
            head=temp;
        }
        return  node;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值