算法_链表相关算法

1、输入一个链表,按链表从尾到头的顺序返回一个ArrayList

思路:创建一个栈来作为中间介质,先把链表中的值都压进栈中,然后再把栈中的元素添加到链表中;

import java.util.ArrayList;
import java.util.Stack;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list=new ArrayList<Integer>();
        if(listNode==null){
            return list;
        }
        Stack<Integer> sta=new Stack<Integer>();
        while(listNode!=null){
            sta.push(listNode.val);
            listNode=listNode.next;
        }
        while(!sta.isEmpty()){
            list.add(sta.pop());
        }
        return list;
    }
}

2、用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型

思路:
入队:直接将元素添加到栈中
出队:先将栈1中的元素全部转移到栈2中,再从栈2中取出栈顶元素。还需将栈2中剩余元素压入栈1中,这样就还原了。

import java.util.Stack;
public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        stack1.push(node);
    }
    public int pop() {
        while(!stack1.isEmpty()){
            stack2.push(stack1.pop());
        }
        int first=stack2.pop();
        while(!stack2.isEmpty()){
            stack1.push(stack2.pop());
        }
        return first;
    }
}

3、输入一个链表,输出该链表中倒数第k个结点

思路:遍历链表计算出链表的长度,再遍历cout-k个结点

public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        int count=0;
        ListNode temp=head;
        while(temp!=null){
            temp=temp.next;
            count++;
        }
        if(count<k){
            return null;
        }
        ListNode node=head;
        while((count-k)!=0){
             node=node.next;
             count--;
        }
        return node;
    }
}

4、输入一个链表,反转链表后,输出新链表的表头

思路:遍历链表,先保留next结点,现结点的下一个结点指向前一个结点,前结点后移,现结点指向next结点。

public class Solution {
    public ListNode ReverseList(ListNode head) {
        if(head==null){
            return head;
        }
        ListNode pre=null;
        ListNode next=null;
        while(head!=null){
            next=head.next;
            head.next=pre;
            pre=head;
            head=next;
        }
        return pre;
    }
}

5、输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

思路:新建一个链表,对比链表1结点与链表2结点值的大小,小者添加到新链表中。递归下一个结点,一次添加到链表里;

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1==null){
            return list2;
        }
        if(list2==null){
            return list1;
        }
        ListNode newNode=null;
        if(list1.val>list2.val){
            newNode=list2;
            newNode.next=Merge(list1,list2.next);
        }else{
            newNode=list1;
            newNode.next=Merge(list1.next,list2);
        }
        return newNode;
    }
}

6、输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

思路:一个个压栈,压栈的过程中也可以出栈,只要栈顶元素和序列2对应元素匹配即可出栈。最后依次对比出栈,栈为空即为正确

import java.util.ArrayList;
import java.util.Stack;
public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
        if(pushA.length==0||popA.length==0){
            return false;
        }
        int count=0;
        Stack<Integer> s=new Stack<Integer>();
        for(int i=0;i<pushA.length;i++){
            s.push(pushA[i]);
            while(!s.isEmpty() && s.peek()==popA[count]){
                s.pop();
                count++;
            }
        }
        if(s.isEmpty()){
            return true;
        }else{
            return false;
        }
    }
}

7、输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

在这里插入图片描述
思路:

/*
public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}
*/
public class Solution {
    public RandomListNode Clone(RandomListNode pHead)
    {
        RandomListNode current=pHead;
        if(pHead==null){
            return pHead;
        }
        //复制根节点  添加到原链表中
        while(current!=null){
            RandomListNode cloneNode=new RandomListNode(current.label);
            RandomListNode nextNode=current.next;
            current.next=cloneNode;
            cloneNode.next=nextNode;
            current=nextNode;
        }
        current=pHead;
        //把下一个任意指针,从原结点复制到现结点中
        while(current!=null){
            current.next.random=current.random==null?null:current.random.next;
            current=current.next.next;
        }
        current=pHead;
        //拆分结点,把原结点和新结点拆开
        RandomListNode nphead=current.next;
        while(current!=null){
            RandomListNode cloneNode=current.next;
            current.next=cloneNode.next;
            cloneNode.next=cloneNode.next==null?null:cloneNode.next.next;
            current=current.next;
        }
        return nphead;
    }
}

8、输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的) 思路:遍历链表计算出链表的长度,对长度做差值;遍历长链表到链表相同位置,依次寻找第一个相等的结点。

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
       if(pHead1==null || pHead2==null){
           return null;
       }
        int count1=0;
        ListNode p1=pHead1;
        while(p1 !=null){
            count1++;
            p1=p1.next;
        }
        int count2=0;
        ListNode p2=pHead2;
        while(p2 !=null){
            count2++;
            p2=p2.next;
        }
        int flag=count1 - count2;
        if(flag>0){
            while(flag>0){
                pHead1=pHead1.next;
                flag--;
            }
            while(pHead1 != pHead2){
                pHead1=pHead1.next;
                pHead2=pHead2.next;
            }
            return pHead1;
        }
        if(flag<=0){
            while(flag<0){
                pHead2=pHead2.next;
                flag++;
            }
            while(pHead1 != pHead2){
                pHead1=pHead1.next;
                pHead2=pHead2.next;
            }
            return pHead1;
        }
        return null;
        
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值