链表算法-回文结构、两个链表公共节点

最近一直在刷算法,以前没有重视这块,偶然巧合下,想到了某几次的面试,虽然没有以这个为主,但是也都有问过算法的题,因为没有这方面的积累,所以心底里一直抗拒,最近也有时间,觉得还是要花时间学习研究算法的东西,锻炼锻炼逻辑思路和解决思路。

学习路程肯定是要把基础掌握好的,你得知道各个名词的含义,如链表是什么,单链表怎么实现,双链表怎么实现,你才能处理把握链表出的方向的算法题,如树,什么是二叉树,二叉搜索树,二三树,红黑树,你知道每个结构的定义以及特性,才能掌握和思考怎么处理,这一定是必然的。

今天弄几个链表算法

1.判断链表回文结构

1.对单链表逆顺序是否与原链表顺序相同,也就是回文链表,如1->2 ->1,那么1->2->1这个就是true,如1->2,那么逆序就是2->1那么就是false;

因为链表有个特点不知道长度,不能随机用下标访问数据,所以需要遍历到最后才能全部知道数据,这道题可以采用先遍历将链表数据存储到数组中,然后采用二分法进行前后对比数据,直到遇到不相等则直接退出循环,返回false,一直相等则就是链表的回文数据,

public boolean isPail (ListNode head) {
 List<Integer> list = new ArrayList();
        ListNode w = head;
        // 将链表数据存储到数组中
        while (w != null) {
            list.add(w.val);
            w = w.next;
        }

        int size = list.size();
        boolean result = true;
        // 将数组长度/2 得到回文顺序交界点
        for (int i = 0; i < size / 2; i++) {
            // 从前往后对比直到交界点,全部都比对完毕
            if (list.get(i).equals(list.get(size - i - 1))) {
            } else {
                result = false;
                break;
            }
        }
        return result;
}

// 节点,是个内部类
public static class ListNode {
        int val;
        ListNode next = null;
}

测试示例

 ListNode ListNode = new ListNode();
        ListNode.val = 1;
        ListNode.next = null;

        ListNode ListNodeNext = new ListNode();
        ListNodeNext.val = 2;
        ListNodeNext.next = null;
        ListNode.next = ListNodeNext;


        ListNode ListNodeNextn = new ListNode();
        ListNodeNextn.val = 3;
        ListNodeNextn.next = null;
        ListNodeNext.next = ListNodeNextn;

        ListNode ListNodeNextns = new ListNode();
        ListNodeNextns.val = 3;
        ListNodeNextns.next = null;
        ListNodeNextn.next = ListNodeNextns;

        ListNode ListNodeNextnn = new ListNode();
        ListNodeNextnn.val = 2;
        ListNodeNextnn.next = null;
        ListNodeNextns.next = ListNodeNextnn;

        ListNode ListNodeNextnns = new ListNode();
        ListNodeNextnns.val = 1;
        ListNodeNextnns.next = null;
        ListNodeNextnn.next = ListNodeNextnns;
        System.out.println(AboutLinked.isPail2(ListNode));

输入:1->2->3->3-2>1返回结果 true

自己写的一个版本,当时主要考虑不想遍历放入数组中,再次进行遍历,所以用了String的字符串拼接方式。

public boolean isPail (ListNode head) {
        String s="";
        String ss ="";
        ListNode w = head;
        while (w != null) {
            s+=w.val+"";
            ss=w.val+ss;;
            w = w.next;
        }
        return s.equals(ss);
    }

这种方式答案是对的,但是性能太差,输入量特多的情况下,会超时反馈不出结果,我想主要原因还是出在了字符串拼接导致的问题,我本想减少代码,减少一些遍历,但是却出现了其他的性能问题,不用StringBuffer的原因是想要倒着拼接,如果使用reverse则负数又会出现问题,

String采用连接运算符(+)效率低下,都是上述循环、大批量数据情况造成的,每做一次"+"就产生个StringBuilder对象,然后append后就扔掉。下次循环再到达时重新产生个StringBuilder对象,然后append字符串,如此循环直至结束。如果我们直接采用StringBuilder对象进行append的话,我们可以节省创建和销毁对象的时间。

2. NC66两个链表的第一个公共节点

输入两个非公共的链表{1,2,3}以及{4,5}和一个公共链表{6,7},塞入到两个公共链表里头,变为{1,2,3,6,7}以及{4,5,6,7},请输出他们的第一个公共节点,那么得到的就是{6,7}

我们需要两个链表一一比对,直到某个链表为空,另一个链表还有值时进行两个链表替换,然后继续对比,本示例当对比空以后将temp赋值为temp2{1,2,3,6,7},temp2赋值为temp则{4,5,6,7},当temp链表走到空时,temp2链表已经赋值为1,那么当temp为空时,就赋值temp2为4,此时temp就为2,就变成了2:4,3:5,6:6 相同直接结束循环,是不是清楚很多,那么代码如下

public class Solution {
 public static class ListNode {
        int val;
        ListNode next = null;
    }
// pHead1={1,2,3,6,7}  pHead2={4,5,6,7}
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode temp = pHead1;
        ListNode temp1 = pHead2;

        while (temp != temp1) {
            // 如果为空互相替换来找出公共节点
            temp = temp!=null?temp.next:pHead2;
            temp1 = temp1!=null?temp1.next:pHead1;
        }
        return temp;
    }

}

咱们就不演示测试了否择还得遍历打印链表,本次案例结果返回6->7

2. NC69-链表中倒数最后k个结点

这个就是得到链表中倒数第几个结点,如 {1,2,3,4,5},然后传入2,则得到{4,5},传入3则得到链表倒数第三个以及之后的节点数据,如果链表的长度不足倒数得结点,则返回空节点

原链表为{1,2,3,4,5} 我需要让快指针走,走的终点是k,走到了k的值以后,再快慢链表一起走,最后返回慢指针就是想要的最后k个结点。

  • 先循环,循环从0开始到k结束,那么第一个循环,快链表指针(fast)={2,3,4,5}

  • 循环到1,fast={3,4,5},假如传的是2,那么循环到此则结束循环

  • 快指针已得到,进行while循环,终止条件是快指针为空,fast={4,5} slow={2,3,4,5}

  • fast={5},slow={3,4,5}

  • fast={},slow={4,5} 结束循环,得到{4,5}

这里可采用快慢指针的思想,这样代码实现就很简单,

 public ListNode FindKthToTail (ListNode pHead, int k) {
        ListNode fast = pHead;
        // 快的指针先走,按k的步长走,如果为空则链表代表不足k个节点,返回空
        for (int i = 0; i < k; i++) {
            if (fast == null)
                return null;
            fast = fast.next;
        }
        // 快指针提前走了指定步长,直到快指针为空,则我们需要的就是慢指针的节点
        ListNode slow = pHead;
        while(fast!=null){
           fast=fast.next;
           slow=slow.next;
        }
        return slow;
    }

我自己有写过一个,思想和这个差不多,但是写完还是比这个复杂了,我采取的是,循环达到k点,就记录一个节点,直到找到空,就把存储的节点的下一个拿到,也就是将{1,2,3,4,5} 循环到3的时候将fast={3,4,5},循环到4的时候判断达不到到k个节点就为空了,如果是,则直接返回,不是就继续last={4,5},这种方式太冗余了,还要进行空啊或者其他不足k的判断,所以我们还是学会和使用简洁方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要验链表是否为回文链表,可以采用以下方法: 1. 使用快慢指针找到链表的中点。 2. 将链表的后半部分反转。 3. 将链表的前半部分与反转后的后半部分进行逐一比较,如果存在不相等的节点,则该链表不是回文链表。 4. 如果链表的所有节点都比较完毕,且没有找到不相等的节点,则该链表回文链表。 具体操作步骤如下: 1. 初始化快慢指针,快指针每次移动两个节点,慢指针每次移动一个节点,直到快指针到达链表末尾。此时慢指针指向链表的中点。 2. 将链表的后半部分反转。可以使用一个新的指针从慢指针位置开始反转,每次将当前节点的next指针指向前一个节点,然后将指针向后移动一个节点,直到到达链表末尾。最后将反转后的链表的头节点保存下来。 3. 分别使用两个指针,一个指向链表的头节点,另一个指向反转后的链表的头节点。逐一比较两个指针指向的节点的值是否相等,如果存在不相等的节点,则该链表不是回文链表。 4. 如果链表的所有节点都比较完毕,且没有找到不相等的节点,则该链表回文链表。 通过以上方法,我们可以检验链表是否为回文链表。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++数据结构算法之判断一个链表是否为回文结构的方法](https://download.csdn.net/download/weixin_38737980/14866827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [判断链表是否为回文链表leetcode-LeetCodeAlgorithm:算法问题](https://download.csdn.net/download/weixin_38660295/19945543)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [判断链表是否为回文链表leetcode-LeetCode:力码](https://download.csdn.net/download/weixin_38600696/19945643)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值