Java刷题-list

一、打印两个有序链表的公共部分

补充一个关于节点的链表构造方法

Node next是设置指针域

import java.io.IOException;这个是报错信息

这是两个lO流

import java.io.BufferedReader;

import java.io.InputStreamReader;

以下的代码可以实现最高效率速度读取

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

 

 类 InputStreamReader是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。如:GBK 
  每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。 为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:  BufferedReader in= new BufferedReader(new InputStreamReader(System.in));

System.in是个字节流

InputStreamReader是个字符流和字节流之间的转换中介

BufferedReader是个字符流
整体意思就是用InputStreamReader这个中介把System.in这个字节流转换成字符流BufferedReader
这样输入的时候就可以不是一个一个字节读,而是一个一个字符读,再加上是个Buffer,效率会高很多。
 

public class Mylinkedlist {
    class Node {
        int value;
        Node next;

        Node(int data) {
            this.value = data;
        }//构造方法
    }

    private Node first; //头节点

    Mylinkedlist() {
        first = null;
    }

    //插入一个节点,在头节点之后插入
    void insertFirst(int value) {
        Node node = new Node(value);
        node.next = first;
        first = node;
    }

    //删除一个节点用tmp表示,在头节点之后进行删除
    Node deleteFirst() {
        Node tmp = first.next;
        first = tmp.next;
        return tmp;
    }

}

网络上很多人用的是IO流速度会比较快

本题主要是对list的使用进行考察,重点要注意的是listgenerate函数如何生成的,对于一个class内所有的方法都要加入static

import java.util.Scanner;

public class Linkedlist1 {
    public static class Node {
        int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

    private static Node listGenerator(int length, String[] numbers) {
        Node head = new Node(Integer.parseInt(numbers[0]));
        Node cur = head;
        for (int i = 1; i < length; i++) {
            cur.next = new Node(Integer.parseInt(numbers[i]));
            cur = cur.next;
        }
        cur.next = null;
        return head;
    }

    public static void printCommonPart(Node head1, Node head2) {
        if (head1 == null || head2 == null) {
            return;
        }
        while (head1 != null && head2 != null) {
            if (head1.value > head2.value) {
                head2 = head2.next;
            } else if (head1.value < head2.value) {
                head1 = head1.next;
            } else {
                System.out.print(head1.value + " ");
                head1 = head1.next;
                head2 = head2.next;
            }
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num1 = sc.nextInt();
        sc.nextLine();
        String str1 = sc.nextLine();
        String[] a = str1.split(" ");

        Node head1 = listGenerator(num1, a);

        int num2 = sc.nextInt();
        sc.nextLine();
        String str2 = sc.nextLine();
        String[] b = str2.split(" ");

        Node head2 = listGenerator(num2, b);
        printCommonPart(head1, head2);

    }
}

二、删除倒数第k个节点

超时了。还是要快点学io流

import java.util.Scanner;

public class Linkedlist2 {
    public static class Node {
        private int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

    public static Node listGenerate(int length, String[] number) {
        Node head = new Node(Integer.parseInt(number[0]));
        Node cur = head;
        for (int i = 1; i < length; i++) {
            cur.next = new Node(Integer.parseInt(number[i]));
            cur = cur.next;
        }
        cur.next = null;
        return head;
    }

    //num_delete是前面一个节点数倒数第4个就是正第1个
    public static Node listDelete(int num_delete, Node head) {
        if (head == null || num_delete < 0) return null;
        else if (num_delete == 0) return head = head.next;
        else {
            Node cur = head;
            for (int i = 0; i < num_delete - 1; i++) {
                cur = cur.next;
            }
            cur.next = cur.next.next;
            return head;
        }

    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int length = sc.nextInt();
        int delete=sc.nextInt();
        sc.nextLine();
        String str1 = sc.nextLine();
        String[] a = str1.split(" ");
        Node head=listGenerate(length,a);
        int num_delete=length-delete;
        head=listDelete(num_delete,head);
        while (head.next!=null){
            System.out.print(head.value);
            System.out.print(" ");
            head=head.next;
        }
        System.out.print(head.value);


    }
}

对于链表学习还是看算法书实现的比较好。

注意头节点的增删问题,这个很重要。

1、查找元素

用一个计数器计数,从0开始判断当前节点的数据域是否为x,不是则next,注意最好不要修改链表的head的值,可以用cur来代替

2、插入元素

新建节点q

找到插入位置的前一个节点pre,这个很重要

q.next=pre.next;

pre.next=q;

3、删除元素

需要找到前驱节点pre

和p删除节点

pre.next=p.next;

三、删除第i个节点

很典型建议背诵

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;


public class Linkedlist3 {
    public static class Node {
        private int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

    public static Node listGenerate(int length, String[] number) {
        Node head = new Node(Integer.parseInt(number[0]));
        Node cur = head;
        for (int i = 1; i < length; i++) {
            cur.next = new Node(Integer.parseInt(number[i]));
            cur = cur.next;
        }
        cur.next = null;
        return head;
    }

    public static Node removeMidNode(Node head, int m) {
        Node cur = head;
        if (head == null || m < 1) return null;
        else if (m == 1) return head = head.next;
        else {
            while (--m != 1) {
                cur = cur.next;
            }
            cur.next = cur.next.next;
            return head;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String[] number = bf.readLine().split(" ");
        int length = Integer.parseInt(number[0]);
        int delete = Integer.parseInt(number[1]);
        String[] a = bf.readLine().split(" ");
        Node head = listGenerate(length, a);
        head=removeMidNode(head,delete);
        StringBuilder str = new StringBuilder();
        while (head!= null) {
            str.append(head.value);
            str.append(" ");
            head = head.next;
        }
        System.out.println(str.toString());

    }


}

四、反转链表

public static Node reverseList(Node head) {
        Node pre = null;
        Node next = null;//pre用来保存先前结点、next用来做临时变量
        while (head != null) {
            next = head.next;
            head.next = pre;
            pre = head;
            head = next;

        }
        return pre;
    }

这段代码很值得学习,首先明确概念引用类型的声明变量都是地址,所以除非new的内容都只是地址值。

1->2->3->4

pre节点存储的是新节点的首地址,next存储是要反转的下一个节点地址。

首先把next赋值头节点的下一个节点,所以指向的值是2。

然后把头节点的下一个节点的指向变为pre空节点。

再将pre进行赋值,赋值头节点,因此现在的反转是1->0,也就是pre->null

最后将头节点赋值,赋值next曾经的下一个节点。

 

还要注意学习一下双链表的构建

import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;


public class Linkedlist4 {
    public static class Node {
        int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

    //双向链表
    public static class DoubleNode {
        int value;
        DoubleNode last;
        DoubleNode next;

        DoubleNode(int value) {
            this.value = value;
        }
    }

    //单向链表的反转
    public static Node listGenerate(int length, String[] number) {
        Node head = new Node(Integer.parseInt(number[0]));
        Node cur = head;
        for (int i = 1; i < length; i++) {
            cur.next = new Node(Integer.parseInt(number[i]));
            cur = cur.next;
        }
        cur.next = null;
        return head;
    }

    //双向链表的反转
    public static DoubleNode D_listGenerate(int length, String[] number) {
        DoubleNode head = new DoubleNode(Integer.parseInt(number[0]));
        DoubleNode cur = head;
        for (int i = 1; i < length; i++) {
            cur.next = new DoubleNode(Integer.parseInt(number[i]));
            cur.next.last = cur;
            cur = cur.next;
        }
        cur.next = null;
        return head;
    }


    public static Node reverseList(Node head) {
        Node pre = null;
        Node next = null;//pre用来保存先前结点、next用来做临时变量
        while (head != null) {
            next = head.next;
            head.next = pre;
            pre = head;
            head = next;
        }
        return pre;
    }

    public static DoubleNode D_reverseList(DoubleNode head) {
        DoubleNode pre = null;
        DoubleNode next = null;
        while (head != null) {
            next = head.next;
            head.next = pre;
            head.last = next;
            pre = head;
            head = next;
        }
        return pre;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int length=Integer.parseInt(bf.readLine());
        String[] number = bf.readLine().split(" ");
        int length2=Integer.parseInt(bf.readLine());
        String[] number2 = bf.readLine().split(" ");
        Node head = listGenerate(length, number);
        DoubleNode head2 = D_listGenerate(length2, number2);
        head = reverseList(head);
        head2=D_reverseList(head2);
        StringBuilder str = new StringBuilder();
        StringBuilder str2 = new StringBuilder();
        while (head != null) {
            str.append(head.value).append(" ");
            head = head.next;
        }
        System.out.println(str.toString());

        while (head2 != null) {
            str2.append(head2.value).append(" ");
            head2 = head2.next;
        }

        System.out.println(str2.toString());
    }

}

五、反转部分单向链表

主要是找到反转的前一个节点和后一个节点,考虑到首节点可能要变化的问题。

import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;



public class Linkedlist5 {
    public static class Node {
        int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

    public static Node listGenerate(int length, String[] num) {
        Node head = new Node(Integer.parseInt(num[0]));
        Node cur = head;
        for (int i = 1; i < length; i++) {
            cur.next = new Node(Integer.parseInt(num[i]));
            cur = cur.next;
        }
        cur.next = null;
        return head;
    }

    public static Node reverseNode(Node head, int from, int to) {
        int len = 0;
        Node node1 = head;
        Node fPre = null;
        Node tPos = null;
        while (node1 != null) {
            len++;
            fPre = len == from - 1 ? node1 : fPre;
            tPos = len == to + 1 ? node1 : tPos;
            node1= node1.next;
        }
        if (from > to || from < 1 || to > len) {
            return head;
        }
        node1 = fPre == null ? head : fPre.next;
        Node pre=tPos;//为转换后的头节点
        Node next=null;
        while (node1!=tPos){
            next=node1.next;
            node1.next=pre;
            pre=node1;
            node1=next;
        }
        if (fPre != null) {
            fPre.next = pre;
            return head;
        }
        return pre;

    }

    public static void main(String[] args) throws IOException {
        BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
        int length=Integer.parseInt(bf.readLine());
        String[] num=bf.readLine().split(" ");
        String[] num2=bf.readLine().split(" ");
        int from=Integer.parseInt(num2[0]);
        int to=Integer.parseInt(num2[1]);
        Node head=listGenerate(length,num);
        head=reverseNode(head,from,to);
        StringBuilder str=new StringBuilder();
        while (head!=null){
            str.append(head.value).append(" ");
            head=head.next;
        }
        System.out.println(str.toString());
    }


}

 六、环型链表约瑟夫问题

注意环型链表的删除

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Linkedlist6 {
    public static class Node {
        int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

   public static Node josephusKill(Node head,int m){
        if(head==null||head.next==head||m<1){
            return head;
        }
        Node last=head;
        while(last.next!=head){
            last=last.next;
        }
        int count=0;
        while(head!=last){
            count++;
            if(count==m){
                last.next=head.next;
                count=0;
            }
            else{
                last=last.next;
            }
            head=last.next;
        }
        return head;

   }

    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        String[] parameters = bufferedReader.readLine().split(" ");
        int l = Integer.parseInt(parameters[0]);
        int m = Integer.parseInt(parameters[1]);
        Node head = new Node(1);
        Node cur = head;
        for (int i = 2; i <= l; i++) {
            cur.next = new Node(i);
            cur = cur.next;
        }
        cur.next = head;
        head = josephusKill(head, m);
        System.out.println(head.value);
    }


}import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Linkedlist6 {
    public static class Node {
        int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

   public static Node josephusKill(Node head,int m){
        if(head==null||head.next==head||m<1){
            return head;
        }
        Node last=head;
        while(last.next!=head){
            last=last.next;
        }
        int count=0;
        while(head!=last){
            count++;
            if(count==m){
                last.next=head.next;
                count=0;
            }
            else{
                last=last.next;
            }
            head=last.next;
        }
        return head;

   }

    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        String[] parameters = bufferedReader.readLine().split(" ");
        int l = Integer.parseInt(parameters[0]);
        int m = Integer.parseInt(parameters[1]);
        Node head = new Node(1);
        Node cur = head;
        for (int i = 2; i <= l; i++) {
            cur.next = new Node(i);
            cur = cur.next;
        }
        cur.next = head;
        head = josephusKill(head, m);
        System.out.println(head.value);
    }


}

七、给定一个链表,请判断该链表是否为回文结构

import java.util.Stack;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Linkedlist7 {
    public static Stack<Integer> st=new Stack<>();
    public static class Node {
        int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

    public static Node listGenerate(int length,String[] num){
        Node head=new Node(Integer.parseInt(num[0]));
        st.push(head.value);
        Node cur=head;
        for(int i=1;i<length;i++){
            cur.next=new Node(Integer.parseInt(num[i]));
            cur=cur.next;
            st.push(cur.value);
        }
        cur.next=null;
        return head;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
        int length=Integer.parseInt(bf.readLine());
        String[] num=bf.readLine().split(" ");
        Node head=listGenerate(length,num);
        int flag=0;
        for(int i=0;i<length;i++){
            if(head.value!=st.pop()) {
                flag=1;
                System.out.println("false");
                break;
            }
            head=head.next;
        }
        if(flag==0) System.out.println("true");
    }


}

八、将单链表按某值划分为左边小、中间相等、右边大的形式

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
class Node{
    public int value;
    public Node next;
    public Node(int value){
        this.value = value;
    }
}
class ListPartition{
    public static Node listPartition(Node head,int pivot){
        if(head == null || head.next == null)
            return head;
        //统计链表长度
        int i = 0;
        Node node = head;
        while(node != null){
            i++;
            node = node.next;
        }
        //创建数组,并填充
        Node[] arr = new Node[i];
        node = head;
        for(i = 0;i < arr.length;i++){
            arr[i] = node;
            node = node.next;
        }
        //对数组进行partition
        partitionArr(arr,pivot);
        //将数组组合成链表
        for(i = 1; i < arr.length; i++){
            arr[i-1].next = arr[i];
        }
        //最后一个的指向
        arr[i-1].next = null;
        return arr[0];
    }
    public static void partitionArr(Node[] arr,int pivot){
        int less = -1;
        int more = arr.length;
        int index = 0;
        while(index < more){
            if(arr[index].value < pivot){
                swap(arr,index++,++less);
            }else if(arr[index].value > pivot){
                swap(arr,index,--more);
            }else{
                index++;
            }
        }
         
    }
    public static void swap(Node[] arr, int i,int j){
        Node temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}
public class Main{
    //创建链表
    private static Node createNode(String[] str,int n){
        Node head = new Node(Integer.parseInt(str[0]));
        Node node = head;
        for(int i=1;i<n;i++){
            Node newNode = new Node(Integer.parseInt(str[i]));
            node.next = newNode;
            node = newNode;
        }
        return head;
    }
        //打印列表
    private static void printList(Node node){
        StringBuilder builder = new StringBuilder();
        while (node != null){
            builder.append(node.value).append(" ");
            node = node.next;
        }
        System.out.println(builder.toString());
    }
    //主函数部分
    public static void main(String[] args) throws IOException{
        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        //创建第一个链表
        String[] s = input.readLine().split(" ");
        int n = Integer.parseInt(s[0]);
        int pivot = Integer.parseInt(s[1]);
        String[] strings1 = input.readLine().split(" ");
        Node list1 = createNode(strings1,n);
        //要操作的函数
        Node node = ListPartition.listPartition(list1,pivot);
        printList(node);
    }
}

这个题目没做出来,很奇怪,我理解就是排序再合成一个链表,但是还是报错。

这个用例有个重要的方法叫做partition,大概就是类似与快速排序的过程  。

九、两个单链表生成相加链表

这个题目需要注意直接相加两个数,java 的整数类型int接受不了,因此需要用到堆栈。并且使用进位的方式来进行记录

变成小学加法题目来做

import java.util.Stack;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Mylinkedlist9 {
    public static class Node {
        int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

    //堆栈存放整数
    public static Stack<Integer> st1 = new Stack<>();
    public static Stack<Integer> st2 = new Stack<>();

    public static Node listGenerate(Stack<Integer> st1, Stack<Integer> st2) {
        //定义接受出栈的元素,cur为进位
        Node head = null;
        Node cur = null;
        int num1 = 0;
        int num2 = 0;
        int sum = 0;
        Boolean ca = false;
        while (!st1.isEmpty() || !st2.isEmpty()) {
            if (!st1.isEmpty()) {
                num1 = st1.pop();
            } else num1 = 0;
            if (!st2.isEmpty()) {
                num2 = st2.pop();
            } else num2 = 0;
            sum = num1 + num2;
            if (ca) {
                sum++;
                ca=false;
            }

            if (sum >= 10) {
                ca = true;//需要进位
                sum = sum - 10;
            }
            head = new Node(sum);
            head.next = cur;
            cur = head;
        }
        if (ca) {
            head = new Node(1);
            head.next = cur;
        }
        return head;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String[] num1 = bf.readLine().split(" ");
        String[] num2 = bf.readLine().split(" ");
        String[] num3 = bf.readLine().split(" ");
        int n = Integer.parseInt(num1[0]);//记录长度
        int m = Integer.parseInt(num1[1]);//记录第二个链表的长度
        for (int i = 0; i < n; i++) {
            st1.push(Integer.parseInt(num2[i]));
        }
        for (int i = 0; i < m; i++) {
            st2.push(Integer.parseInt(num3[i]));
        }
        Node head = listGenerate(st1, st2);
        StringBuilder sb = new StringBuilder();
        while (head != null) {
            sb.append(head.value).append(" ");
            head = head.next;
        }
        System.out.println(sb.toString());
    }


}

十、将单链表的每K个节点之间逆序

我的方法有点投机取巧了,但也能通过==还是看看书上的方法。

最近的题目感觉有些相似,可以考虑跳过了。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.Buffer;
import java.util.Stack;


public class Mylinkedlist10 {
    //节点定义
    public static class Node {
        int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

    //生成链表
    public static Node listGenerate(int length, String[] num) {
        Node head = new Node(Integer.parseInt(num[0]));
        Node cur = head;
        for (int i = 1; i < length; i++) {
            cur.next = new Node(Integer.parseInt(num[i]));
            cur = cur.next;
        }
        cur.next = null;
        return head;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int length = Integer.parseInt(bf.readLine());
        String[] str1 = bf.readLine().split(" ");
        int reverse = Integer.parseInt(bf.readLine());
        Node head = listGenerate(length, str1);
        Stack<Integer> stack = new Stack<>();
        int time = length / reverse;
        String[] str2 = new String[reverse];
        //反转链表
        Node cur = head;
        for (int i = 0; i < time; i++) {
            for (int j = 0; j < reverse; j++) {
                stack.push(cur.value);
                cur = cur.next;
            }
            for (int j = 0; j < reverse; j++) {
                str1[j + reverse * i] = "" + stack.pop();
            }
        }
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < length; i++) {
            str.append(str1[i]).append(" ");
        }
        System.out.println(str.toString());

    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章