程序员代码面试指南(左程云著)java学习笔记
目录
常见问题总结
读取输入数据两种方法 (BufferedReader比较快,不容易出现报错)
1、 Scanner s = new Scanner(System.in); int i = s.nextInt(); 2、 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] inputDate = br.readLine().trim().split(" ");int i = Integer.parseInt(inputDate[0]);
有一题while(fast.next.next != null && fast.next != null)出现了空指针异常的错误。正确应改为while(fast.next != null && fast.next.next != null)
第一章 栈和队列
CD5 设计getMin功能的栈
描述
实现一个特殊功能的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
输入描述:
第一行输入一个整数N,表示对栈进行的操作总数。
下面N行每行输入一个字符串S,表示操作的种类。
如果S为"push",则后面还有一个整数X表示向栈里压入整数X。
如果S为"pop",则表示弹出栈顶操作。
如果S为"getMin",则表示询问当前栈中的最小元素是多少。
输出描述:
对于每个getMin操作,输出一行表示当前栈中的最小元素是多少。
示例1
输入:
6 push 3 push 2 push 1 getMin pop getMin
输出:
1 2
备注:
1<=N<=1000000-1000000<=X<=1000000数据保证没有不合法的操作
解答
import java.util.Scanner;
import java.util.Stack;public class Main
{public static class MyStack1{private Stack<Integer> stackData;private Stack<Integer> stackMin;public MyStack1(){this.stackData = new Stack<Integer>();this.stackMin = new Stack<Integer>();}public void push(int newNum){if (this.stackMin.isEmpty()){this.stackMin.push(newNum);}else if (newNum <= this.getMin()){this.stackMin.push(newNum);}this.stackData.push(newNum);}public int getMin(){if (this.stackMin.isEmpty()){throw new RuntimeException("Your stack is empty.");}return this.stackMin.peek();}public int pop(){if (this.stackData.isEmpty()){throw new RuntimeException("Your stack is empty.");}int value = this.stackData.pop();if (value == this.getMin()){this.stackMin.pop();}return value;}}public static class MyStack2{private Stack<Integer> stackData;private Stack<Integer> stackMin;public MyStack2(){this.stackData = new Stack<Integer>();this.stackMin = new Stack<Integer>();}public void push(int newNum){if (stackMin.isEmpty()){this.stackMin.push(newNum);}else if (newNum <= this.getMin()){this.stackMin.push(newNum);}else{int newMin = this.stackMin.peek();this.stackMin.push(newMin);}this.stackData.push(newNum);}public int getMin(){if (this.stackData.isEmpty()){throw new RuntimeException("Your stack is empty");}return this.stackMin.peek();}public int pop(){if (this.stackData.isEmpty()){throw new RuntimeException("Your stack is empty");}this.stackMin.pop();return this.stackData.pop();}}public static void main(String[] args){/*MyStack1 myStack1 = new MyStack1();Scanner scanner = new Scanner(System.in);int n = Integer.parseInt(scanner.nextLine());for (int i = 1; i <= n; i++){String[] inputData = scanner.nextLine().split(" ");if (inputData[0].equals("push")){myStack1.push(Integer.parseInt(inputData[1]));}else if (inputData[0].equals("pop")){myStack1.pop();}else if (inputData[0].equals("getMin")){System.out.println(myStack1.getMin());}}scanner.close();*/MyStack2 myStack2 = new MyStack2();Scanner scanner = new Scanner(System.in);int n = Integer.parseInt(scanner.nextLine());for (int i = 1; i <= n; i++){String[] inputData = scanner.nextLine().split(" ");if (inputData[0].equals("push")){myStack2.push(Integer.parseInt(inputData[1]));}else if (inputData[0].equals("pop")){myStack2.pop();}else if (inputData[0].equals("getMin")){System.out.println(myStack2.getMin());}}scanner.close();}
}
CD6 由两个栈组成的队列
描述
用两个栈实现队列,支持队列的基本操作。
输入描述:
第一行输入一个整数N,表示对队列进行的操作总数。
下面N行每行输入一个字符串S,表示操作的种类。
如果S为"add",则后面还有一个整数X表示向队列尾部加入整数X。
如果S为"poll",则表示弹出队列头部操作。
如果S为"peek",则表示询问当前队列中头部元素是多少。
输出描述:
对于每一个为"peek"的操作,输出一行表示当前队列中头部元素是多少。
示例1
输入:
6 add 1 add 2 add 3 peek poll peek
输出:
1 2
备注:
1<=N<=1000000-1000000<=X<=1000000数据保证没有不合法的操作
解答
import java.util.Scanner;
import java.util.Stack;public class Main
{public static class TwoStacksQueue{// 定义两个栈StackPush\ StackPoppublic Stack<Integer> StackPush;public Stack<Integer> StackPop;// 构造函数public TwoStacksQueue(){this.StackPush = new Stack<Integer>();this.StackPop = new Stack<Integer>();}// pushToPop函数// 两个前提条件: stackPop非空才能倒入, stackPush必须倒完public void pushToPop(){if (this.StackPop.isEmpty()){while (!this.StackPush.isEmpty()){this.StackPop.push(this.StackPush.pop());}}}// add函数public void add(int x){this.StackPush.push(x);pushToPop();}// poll函数public int poll(){// 如果栈都为空则报错if (this.StackPush.isEmpty() && this.StackPop.isEmpty()){throw new RuntimeException("Your queue is empty");}pushToPop();return this.StackPop.pop();}// peek函数public int peek(){if (this.StackPush.isEmpty() && this.StackPop.isEmpty()){throw new RuntimeException("Your queue is empty");}pushToPop();return this.StackPop.peek();}}public static void main(String[] args) {TwoStacksQueue queue = new TwoStacksQueue();Scanner scanner = new Scanner(System.in);int n = Integer.parseInt(scanner.nextLine());for (int i = 1; i <= n; i++){String[] inputData = scanner.nextLine().split(" ");if (inputData[0].equals("add")){queue.add(Integer.parseInt(inputData[1]));}else if (inputData[0].equals("poll")){queue.poll();}else if (inputData[0].equals("peek")){System.out.println(queue.peek());}}scanner.close();}
}
CD7 用递归函数和栈逆序一个栈
描述
一个栈依次压入1,2,3,4,5,那么从栈顶到栈底分别为5,4,3,2,1。将这个栈转置后,从栈顶到栈底为1,2,3,4,5,也就是实现栈中元素的逆序,但是只能用递归函数来实现,不能用其他数据结构。
输入描述:
输入数据第一行一个整数N为栈中元素的个数。
接下来一行N个整数X_iX**i表示一个栈依次压入的每个元素。
输出描述:
输出一行表示栈中元素逆序后的栈顶到栈底的每个元素
示例1
输入:
5 1 2 3 4 5
输出:
1 2 3 4 5
解答
import java.util.Scanner;
import java.util.Stack;public class Main
{// 递归函数一:将栈底的元素返回并移除public static int getAndRemoveLastElement(Stack<Integer> stack){// 记录位置方便递归int x = stack.pop();if (stack.isEmpty()){return x;}else{int last = getAndRemoveLastElement(stack);stack.push(x); // 恢复原来顺序return last;}}public static void reverse(Stack<Integer> stack){if (stack.isEmpty()){return ;}int x = getAndRemoveLastElement(stack);reverse(stack);stack.push(x);}public static void main(String[] args){Stack<Integer> stack = new Stack<>();Scanner scanner = new Scanner(System.in);int n = Integer.parseInt(scanner.nextLine());for (int i = 1; i <= n; i++){int x = scanner.nextInt();stack.push(x);}reverse(stack);while (!stack.isEmpty()){System.out.print(stack.pop() + " ");}System.out.println();}
}
CD13 用一个栈实现另一个栈的排序
描述
一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。除此之外,可以申请新的变量,但不能申请额外的数据结构。如何完成排序?
输入描述:
第一行输入一个N,表示栈中元素的个数
第二行输入N个整数a_ia**i表示栈顶到栈底的各个元素
输出描述:
输出一行表示排序后的栈中栈顶到栈底的各个元素。
示例1
输入:
5 5 8 4 3 6
输出:
8 6 5 4 3
备注:
1 <= N <= 10000
-1000000 <= a_nan <= 1000000
代码
import java.util.Scanner;
import java.util.Stack;public class Main
{// 要排序的栈为stack, 辅助栈为help, 在stack栈进行pop操作,弹出的元素记作cur// 分两种情况讨论: 1、 cur <= help栈顶元素, 则将cur直接压入help栈中// 2、 cur > help栈顶元素 stack.push(help.pop())直到cur <= help栈顶元素位置, 最后把cur压入help中public static void sortStackByStack(Stack<Integer> stack){Stack<Integer> help = new Stack<>();while (!stack.isEmpty()){int cur = stack.pop();while (!help.isEmpty() && cur > help.peek()){stack.push(help.pop());}help.push(cur);}while (!help.isEmpty()){stack.push(help.pop());}}public static void main(String[] args){Scanner scanner = new Scanner(System.in);Stack<Integer> stack = new Stack<>();int n = Integer.valueOf(scanner.nextLine());// 读入待排序数据for (int i = 0; i < n; i++){int x = scanner.nextInt();stack.push(x);}sortStackByStack(stack);// 输出Stack中排好序的结果while (!stack.isEmpty()){System.out.print(stack.pop() + " ");}System.out.println();}
}
CD15 生成窗口最大值数组
描述
有一个整型数组arr和一个大小为w的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置,求每一种窗口状态下的最大值。(如果数组长度为n,窗口大小为w,则一共产生n-w+1个窗口的最大值)
输入描述:
第一行输入n和w,分别代表数组长度和窗口大小
第二行输入n个整数X_iX**i,表示数组中的各个元素
输出描述:
输出一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值
示例1
输入:
8 3 4 3 5 4 3 3 6 7
输出:
5 5 5 4 6 7
说明:
例如,数组为[4,3,5,4,3,3,6,7],窗口大小为3时:[4 3 5] 4 3 3 6 7 窗口中最大值为54 [3 5 4] 3 3 6 7 窗口中最大值为54 3 [5 4 3] 3 6 7 窗口中最大值为54 3 5 [4 3 3] 6 7 窗口中最大值为44 3 5 4 [3 3 6] 7 窗口中最大值为64 3 5 4 3 [3 6 7] 窗口中最大值为7输出的结果为{5 5 5 4 6 7}
备注:
1\le w \le n \le 10000001≤w≤n≤1000000 -1000000 \le X_i \le 1000000−1000000≤Xi≤1000000
解答
import java.util.LinkedList;
import java.util.Scanner;public class Main
{public static int[] getMaxWindow(int[] arr, int w){// 检验参数是否有效if (arr == null && w < 1 && arr.length < w){return null;}LinkedList<Integer> qmax = new LinkedList<>();int[] res = new int[arr.length - w + 1];int index = 0;for (int i = 0; i < arr.length; i++){while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[i] ){qmax.pollLast();}qmax.addLast(i);// {0, 1,} 2, 3, 4... w = 2// 当 i = 2时, 0出队 也就是 i - w == qmax.peekFirst() 队首元素出队// qmax要溢出时, 队首元素出队if (qmax.peekFirst() == i - w){qmax.pollFirst();}if (i >= w - 1){// 至少检索了w个元素后,才能把队首元素下标对应值放入res数组中res[index++] = arr[qmax.peekFirst()];}}return res;}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String[] inputData = scanner.nextLine().split(" ");int len = Integer.parseInt(inputData[0]);int w = Integer.parseInt(inputData[1]);int[] arr = new int[len];int[] res = new int[len - w + 1];int i = 0;for (i = 0; i < len; i++){int x = scanner.nextInt();arr[i] = x;}res = getMaxWindow(arr, w);for (i = 0; i < res.length; i++){System.out.print(res[i] + " ");}System.out.println();}
}
CD101 单调栈结构
描述
给定一个不含有重复值的数组 arr,找到每一个 i 位置左边和右边离 i 位置最近且值比 arr[i] 小的位置。返回所有位置相应的信息。
输入描述:
第一行输入一个数字 n,表示数组 arr 的长度。
以下一行输出 n个数字,表示数组的值。
输出描述:
输出n行,每行两个数字 L 和 R,如果不存在,则值为-1,下标从0开始。
示例1
输入:
7 3 4 1 5 6 2 7
复制
输出:
-1 2 0 2 -1 -1 2 5 3 5 2 -1 5 -1
复制
备注:
1 \le n \le 10000001≤n≤1000000 -1000000 \le arr_i \le 1000000−1000000≤arri≤1000000
解答
import java.util.Scanner;
import java.util.Stack;public class Main
{public static int[][] rightWay(int[] arr){int[][] res = new int[arr.length][2];for (int i = 0; i < arr.length; i++){int leftLessIndex = -1;int rightLessIndex = -1;int cur = i - 1;while (cur >= 0){if (arr[cur] < arr[i]){leftLessIndex = cur;break;}cur--;}cur = i + 1;while (cur < arr.length){if (arr[cur] < arr[i]){rightLessIndex = cur;break;}cur++;}res[i][0] = leftLessIndex;res[i][1] = rightLessIndex;}return res;}public static int[][] getNearLessNoRepeat(int[] arr){int[][] res = new int[arr.length][2];Stack<Integer> stack = new Stack<>();for (int i = 0; i < arr.length; i++){while (!stack.isEmpty() && arr[stack.peek()] > arr[i]){int index = stack.pop();int leftLessIndex = stack.isEmpty() ? -1 : stack.peek();int rightLessIndex = i;res[index][0] = leftLessIndex;res[index][1] = rightLessIndex;}stack.push(i);}while (!stack.isEmpty()){int popIndex = stack.pop();res[popIndex][1] = -1; // 结算阶段rightLessIndex为-1, 因为没有数使它们弹出res[popIndex][0] = stack.isEmpty() ? -1 : stack.peek();// 判断弹出的数下面有没有数, 如果没有rightLessIndex为-1; 如果有则为下面数的下标}return res;}public static void main(String[] args) {Scanner s = new Scanner(System.in);int n = Integer.parseInt(s.nextLine());int[] arr = new int[n];for (int i = 0; i < n; i++){arr[i] = s.nextInt();}// int[][] res = rightWay(arr);int[][] res = getNearLessNoRepeat(arr);for (int i = 0; i < res.length; i++){System.out.println(res[i][0] + " " + res[i][1]);}}
}
CD188 单调栈结构(进阶)
描述
给定一个可能含有重复值的数组 arr,找到每一个 i 位置左边和右边离 i 位置最近且值比 arr[i] 小的位置。返回所有位置相应的信息。
输入描述:
第一行输入一个数字 n,表示数组 arr 的长度。
以下一行输入 n 个数字,表示数组的值输出描述:
输出n行,每行两个数字 L 和 R,如果不存在,则值为 -1,下标从 0 开始。
示例1
输入:
7 3 4 1 5 6 2 7
输出:
-1 2 0 2 -1 -1 2 5 3 5 2 -1 5 -1
备注:
1 \leq n \leq 10000001≤n≤1000000 -1000000 \leq arr_i \leq 1000000−1000000≤arri≤1000000
解答
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;public class Main
{public static int[][] getNearLess(int[] arr){int[][] res = new int[arr.length][2];Stack<List<Integer>> stack = new Stack<>();for (int i = 0; i < res.length; i++){while (!stack.isEmpty() && arr[i] < arr[stack.peek().get(0)]){List<Integer> popList = stack.pop();// 取出位于下面的列表中,最晚加入的那个int leftLessIndex = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size() - 1);for (Integer x : popList){res[x][0] = leftLessIndex;res[x][1] = i;}}// 当前数比stack栈顶数相等if (!stack.isEmpty() && arr[stack.peek().get(0)] == arr[i]){stack.peek().add(i);}else{// 当前数比stack栈顶数大或者此时为空栈ArrayList<Integer> list = new ArrayList<>();list.add(i);stack.push(list);}}while (!stack.isEmpty()){List<Integer> popList = stack.pop();int leftLessIndex = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size() - 1);for (Integer x : popList){res[x][0] = leftLessIndex;res[x][1] = -1;}}return res;}public static void main(String[] args) {Scanner s = new Scanner(System.in);int n = Integer.parseInt(s.nextLine());int[] arr = new int[n];String[] str = s.nextLine().split(" ");for (int i = 0; i < n; i++){arr[i] = Integer.parseInt(str[i]);}int[][] res = getNearLess(arr);for (int i = 0; i < res.length; i++){System.out.println(res[i][0] + " " + res[i][1]);}}
}
第二章 链表问题
CD48 打印两个升序链表的公共部分
描述
给定两个升序链表,打印两个升序链表的公共部分。
输入描述:
第一个链表的长度为 n。
第二个链表的长度为 m。
链表结点的值为 val。
输出描述:
输出一行整数表示两个升序链表的公共部分的值 (按升序输出)。
示例1
输入:
4 1 2 3 4 5 1 2 3 5 6
输出:
1 2 3
备注:
1 \le n,m\le 10000001≤n,m≤1000000 INTMIN \le val \le INTMAXINTMIN≤val≤INTMAX
解答
import java.util.Scanner;public class Main
{public static class Node{public int value;public Node next;public Node(int v){this.value = v;}}public static void printCommonPart(Node head1, Node head2){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 scanner = new Scanner(System.in);int m = 0, n = 0;m = Integer.parseInt(scanner.nextLine());Node head1 = new Node(scanner.nextInt());Node cur = head1;for (int i = 1; i < m; i++){cur.next = new Node(scanner.nextInt());cur = cur.next;}scanner.nextLine();n = Integer.parseInt(scanner.nextLine());Node head2 = new Node(scanner.nextInt());cur = head2;for (int i = 1; i < n; i++){cur.next = new Node(scanner.nextInt());cur = cur.next;}printCommonPart(head1, head2);}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dqnppjTG-1642684708381)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220119210416383.png)]
CD49 在链表中删除倒数第K个节点
描述
给出一个单链表,返回删除单链表的倒数第 K 个节点后的链表。
输入描述:
第一行输入两个正整数 n, K ,分别表示链表的长度和要删除单链表倒数第K个节点。 接下来一行有 n 个整数,依次表示单链表中的各个节点的节点值val。
输出描述:
在给定的函数内返回删除倒数第K个节点后的链表的头指针。
示例1
输入:
5 4 1 2 3 4 5
输出:
1 3 4 5
备注:
1 \le K \le n \le 10000001≤K≤n≤1000000 -1000000 \le val \le 1000000−1000000≤val≤1000000
解答
import java.util.Scanner;public class Main
{public static class Node{public int value;public Node next;public Node(int value){this.value = value;}}public static Node removeLastNode(Node head, int i){if (head == null || i < 1){return head;}Node cur = head;while (cur != null){i--;cur = cur.next;}if (i > 0){// i > 0 不用调整链表}else if (i == 0){// 要删除头结点head = head.next;}else{cur = head;i++;while (i != 0){i++;cur = cur.next;}cur.next = cur.next.next;}return head;}public static void main(String[] args) {Scanner s = new Scanner(System.in);int m = s.nextInt(), k = s.nextInt();s.nextLine();Node head1 = new Node(s.nextInt());Node cur = head1;for (int i = 1; i < m; i++){cur.next = new Node(s.nextInt());cur = cur.next;}removeLastNode(head1, k);cur = head1;while (cur != null){System.out.print(cur.value + " ");cur = cur.next;}System.out.println();}}
CD106 删除链表的中间节点
描述
给定一个链表,实现删除链表第 K 个节点的函数。
输入描述:
n 表示链表的长度。
m 表示删除链表第几个节点。
val 表示链表节点的值。
输出描述:
在给定的函数中返回链表的头指针。
示例1
输入:
5 3 1 2 3 4 5
输出:
1 2 4 5
备注:
1 \le K \le n \le 10000001≤K≤n≤1000000 -1000000 \le val \le 1000000−1000000≤val≤1000000
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NlfKmD2M-1642684708385)(C:\Users\lenovo\Desktop\资源\IMG_20220119_224721.jpg)]
解答
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;public class Main
{public static class Node{public int value;public Node next;public Node(int v){this.value = v;}}/*public static Node removeMidNode(Node head){if (head == null || head.next == null){return head;}if (head.next.next == null){return head.next;}Node slow = head;Node fast = head.next.next;// 使用快慢指针法 快指针一次走两步,慢指针一次走一步// fast , slow = head 初始化// fast->next == null || fast->next->next == null 时 slow 指针为要删除的那个// 因此 fast初始化要改成fast = head->next->next;while (fast.next != null && fast.next.next != null){fast = fast.next.next;slow = slow.next;}slow.next = slow.next.next;return head;}public static Node removeByRatio(Node head, int a, int b){// 我们假设链表的节点总数为n// 我们要删除的节点 (double) a * (double) n / (double) b 然后再向上取整if (a < 1 || a > b){// 分母比1小 或者 分数>1 为非法参数return null;}int n = 0;Node cur = head;while (cur != null){n++;cur = cur.next;}n = (int) Math.ceil((double)(a * n) / (double) (b));if (n == 1){head = head.next;}else if (n > 1){cur = head;n--;while (n > 1){cur = cur.next;n--;}cur.next = cur.next.next;}return head;}public static void main(String[] args) {// 实例输入// 5// 1 2 3 4 5//输出// 1 2 4 5Scanner s = new Scanner(System.in);int m = Integer.parseInt(s.nextLine());Node head = new Node(s.nextInt());Node cur = head;for (int i = 1; i < m; i++){cur.next = new Node(s.nextInt());cur = cur.next;}// removeMidNode(head);// 链表为1->2->3->4->5// a = 1 b = 3 删除第二个节点// 输出 1->3->4->5s.nextLine();int a = s.nextInt(), b = s.nextInt();removeByRatio(head, a, b);cur = head;while (cur != null){System.out.print(cur.value + " ");cur = cur.next;}System.out.println();}*/public static Node removeKNode(Node head, int k){if (head == null || k < 1){return head;}if (k == 1){return head.next;}Node cur = head;k--;while (k > 1){cur = cur.next;k--;}cur.next = cur.next.next;return head;}public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader( System.in ) );String[] inputData = br.readLine().trim().split(" ");int n = Integer.parseInt(inputData[0]), k = Integer.parseInt(inputData[1]);inputData = br.readLine().trim().split(" ");Node head = new Node(Integer.parseInt(inputData[0]));Node cur = head;for (int i = 1; i < n; i++){cur.next = new Node(Integer.parseInt(inputData[i]));cur = cur.next;}removeKNode(head, k);cur = head;while (cur != null){System.out.print(cur.value + " ");cur = cur.next;}System.out.println();}
}
CD107 反转单向链表
描述
实现反转单向链表和双向链表的函数。
如 1->2->3 反转后变成 3->2->1。
输入描述:
第一行一个整数 n,表示单链表的长度。
第二行 n 个整数 val 表示单链表的各个节点。
第三行一个整数 m,表示双链表的长度。
第四行 m 个整数 val 表示双链表的各个节点。
输出描述:
在给定的函数内返回相应链表的头指针。
示例1
输入:
3 1 2 3 4 1 2 3 4
输出:
3 2 1 4 3 2 1
备注:
1 \le n,m\le10000001≤n,m≤1000000 -1000000 \le val \le 1000000−1000000≤val≤1000000
解答
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;public class Main
{public static class Node{public int value;public Node next;public Node(int value){this.value = value;}}public static class DoubleNode{public int value;public DoubleNode last;public DoubleNode next;public DoubleNode(int v){this.value = v;}}public static Node reverseList(Node head){Node pre = null;Node next = null;while (head != null){next = head.next;head.next = pre;pre = head;head = next;}return pre;}public static DoubleNode reverseDoubleNodeList(DoubleNode head){DoubleNode pre = null;DoubleNode next = null;while (head != null){next = head.next;head.last = next;head.next = pre; // 通过这两步head节点完成了反转pre = head;head = next;}return pre; // 注意输出是pre不是head}public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] inputData = br.readLine().trim().split(" ");int m = Integer.parseInt(inputData[0]);inputData = br.readLine().trim().split(" ");Node head1 = new Node(Integer.parseInt(inputData[0]));Node cur = head1;for (int i = 1; i < m; i++){cur.next = new Node(Integer.parseInt(inputData[i]));cur = cur.next;}inputData = br.readLine().trim().split(" ");int n = Integer.parseInt(inputData[0]);inputData = br.readLine().trim().split(" ");DoubleNode head2 = new DoubleNode(Integer.parseInt(inputData[0]));DoubleNode pre = null, current = head2, next = null;for (int i = 1; i < n; i++){current.next = new DoubleNode(Integer.parseInt(inputData[i]));current.last = pre;pre = current;current = current.next;next = current.next;}head1 = reverseList(head1);head2 = reverseDoubleNodeList(head2);cur = head1;while (cur != null){System.out.print(cur.value + " ");cur = cur.next;}System.out.println();current = head2;while (current != null){System.out.print(current.value + " ");current = current.next;}System.out.println();}
}
CD108 反转部分单向链表
描述
给定一个单链表,在链表中把第 L 个节点到第 R 个节点这一部分进行反转。
输入描述:
n 表示单链表的长度。
val 表示单链表各个节点的值。
L 表示翻转区间的左端点。
R 表示翻转区间的右端点。
输出描述:
在给定的函数中返回指定链表的头指针。
示例1
输入:
5 1 2 3 4 5 1 3
输出:
3 2 1 4 5
备注:
1 \le n \le 10000001≤n≤1000000 1 \leq L \leq R \leq n1≤L≤R≤n -1000000 \le val \le 1000000−1000000≤val≤1000000
解答
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;public class Main
{public static class Node{public int value;public Node next;public Node(int value){this.value = value;}}public static Node reversePart(Node head, int from, int to){int len = 0;Node cur = head;Node fromPre = null, toNext = null;while (cur != null){len++;fromPre = (len == from - 1) ? cur : fromPre; // 找到反转部分的头结点前面一个节点toNext = (len == to + 1) ? cur : toNext; // 找到反转部分的头结点后面一个节点cur = cur.next;}if (from > to || from < 1 || to > len){// 不满足题目 1<=from<=to<=N的条件,返回头结点return head;}Node node1 = (fromPre == null) ? head : fromPre.next;Node node2 = node1.next;node1.next = toNext;Node next = null;while (node2 != toNext){next = node2.next;node2.next = node1;node1 = node2;node2 = next;}if (fromPre != null){fromPre.next = node1;return head;}else{return node1;}}public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] inputData = br.readLine().trim().split(" ");int m = Integer.parseInt(inputData[0]);inputData = br.readLine().trim().split(" ");Node head = new Node(Integer.parseInt(inputData[0]));Node cur = head;for (int i = 1; i < m; i++){cur.next = new Node(Integer.parseInt(inputData[i]));cur = cur.next;}inputData = br.readLine().trim().split(" ");int from = Integer.parseInt(inputData[0]), to = Integer.parseInt(inputData[1]);head = reversePart(head, from, to);cur = head;while (cur != null){System.out.print(cur.value + " ");cur = cur.next;}System.out.println();}}
CD111 判断一个链表是否为回文结构
描述
给定一个链表,请判断该链表是否为回文结构。
输入描述:
n 表示链表的长度
ai 表示链表的各个节点的值。
输出描述:
如果为回文结构输出 “true” , 否则输出 “false”。
示例1
输入:
4 1 2 2 1
输出:
true
备注:
1 \le n \le 10000001≤n≤1000000 -1000000 \le a_i \le 1000000−1000000≤ai≤1000000
解答
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;public class Main
{public static class Node{public int value;public Node next;public Node(int v){this.value = v;}}public static boolean isPalindrome1(Node head){Stack<Integer> stack = new Stack<>();Node cur = head;while (cur != null){stack.push(cur.value);cur = cur.next;}cur = head;while (cur != null){if (cur.value != stack.pop()){return false;}cur = cur.next;}return true;}public static boolean isPalindrome2(Node head){if (head == null || head.next == null){return true;}// 利用快慢指针方法将链表右半部分放入栈中和链表左半部分比较Node fast = head, slow = head.next; // 注意慢指针slow = head.next; 通过画图得到规律Stack<Node> stack = new Stack<>();// !!! 我第一次做题把fast.next != null && fast.next.next != null顺序反过来了,// 出现了空指针异常的报错while (fast.next != null && fast.next.next != null){fast = fast.next.next;slow = slow.next;}while (slow != null){stack.push(slow);slow = slow.next;}while (! stack.isEmpty()){if (stack.pop().value != head.value){return false;}head = head.next;}return true;}public static void main(String[] args) throws IOException, NullPointerException{BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] inputData = br.readLine().trim().split(" ");int m = Integer.parseInt(inputData[0]);inputData = br.readLine().trim().split(" ");Node head = new Node(Integer.parseInt(inputData[0]));Node cur = head;for (int i = 1; i < m; i++){cur.next = new Node(Integer.parseInt(inputData[i]));cur = cur.next;}// System.out.println(isPalindrome1(head));System.out.println(isPalindrome2(head));}
}
CD112 判断一个链表是否为回文结构(进阶)
描述
给定一个链表,请判断该链表是否为回文结构。
输入描述:
n 表示链表的长度。
ai 表示链表节点的值输出描述:
如果为回文结构输出 “true” , 否则输出 “false”。
示例1
输入:
5 1 2 3 2 1
输出:
true
备注:
1 \le n \le 20000001≤n≤2000000 -1000000 \le a_i \le 1000000−1000000≤ai≤1000000
解答
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;public class Main
{public static class Node{public int value;public Node next;public Node (int value){this.value = value;}}public static boolean isPalindromePlus(Node head){if (head == null || head.next == null){return true;}Node node1 = head, node2 = head; // node1为快指针,node2为慢指针while (node1.next != null && node1.next.next != null){node1 = node1.next.next;node2 = node2.next;}// 此时node1到了最后, node2到了中间(后半段开头在node2+1节点处)node1 = node2.next;node2.next = null;Node node3 = null;while (node1 != null){node3 = node1.next;node1.next = node2;node2 = node1;node1 = node3;}// node2为最后一个节点node3 = node2; // 保存最后一个节点node1 = head;boolean res = true;while (node1 != null && node2 != null){if (node1.value != node2.value){res = false;break;}node1 = node1.next;node2 = node2.next;}// 恢复原来的链表node1 = node3.next;node3.next = null;while(node1 != null){node2 = node1.next;node1.next = node3;node3 = node1;node1 = node2;}return res;}public static void main(String[] args) throws IOException, NullPointerException{BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] inputData = br.readLine().trim().split(" ");int m = Integer.parseInt(inputData[0]);inputData = br.readLine().trim().split(" ");Node head = new Node(Integer.parseInt(inputData[0]));Node cur = head;for (int i = 1; i < m; i++){cur.next = new Node(Integer.parseInt(inputData[i]));cur = cur.next;}// System.out.println(isPalindrome1(head));System.out.println(isPalindromePlus(head));}
}
程序员代码面试指南(左程云著)java学习笔记相关推荐
- 《程序员代码面试指南第二版》Python实现(个人读书笔记)
说明 最近在读左神的书---<程序员代码面试指南-IT名企算法与数据结构题目最优解(第二版)>以及看了一些左神的基础.进阶.高频等视频课程,为了记录自己的学习成果,并且方便以后查看,将自己 ...
- 程序员代码面试指南第二版 4.猫狗队列
welcome to my blog 程序员代码面试指南第二版 4.猫狗队列 题目描述 题目描述 实现一种猫狗队列的结构,要求如下: 1. 用户可以调用 add 方法将 cat 或者 dog 放入队列 ...
- 算法大神左程云耗尽5年心血分享程序员代码面试指南第2版文档
前言 学习是一种基础性的能力.然而,"吾生也有涯,而知也无涯.",如果学习不注意方法,则会"以有涯随无涯,殆矣". 学习就像吃饭睡觉一样,是人的一种本能,人人都 ...
- 《程序员代码面试指南》第三章 二叉树问题 二叉树节点间的最大距离问题
题目 二叉树节点间的最大距离问题 java代码 package com.lizhouwei.chapter3;/*** @Description:二叉树节点间的最大距离问题* @Author: liz ...
- 《程序员代码面试指南》第五章 字符串问题 拼接所有字符串产生字典顺序最小的大写字符串...
题目 拼接所有字符串产生字典顺序最小的大写字符串 java代码 努力中.... 转载于:https://www.cnblogs.com/lizhouwei/p/8955158.html
- 《程序员代码面试指南》第二章 链表问题 构造链表和节点的实体
准备一些链表和节点的实体,方便后面使用 java代码 /*** @Description:构造一个链表实体,方便后续构造链表* @Author: lizhouwei* @CreateDate: 201 ...
- 《程序员代码面试指南》第二章 链表问题 在单链表和双链表中删除倒数第K个节点...
题目 在单链表和双链表中删除倒数第K个节点 java代码 /*** @Description:在单链表和双链表中删除倒数第K个节点* @Author: lizhouwei* @CreateDate: ...
- 《程序员代码面试指南》第七章 位运算 在其他数都出现k 次的数组中找到只出现一次的数...
题目 在其他数都出现k 次的数组中找到只出现一次的数 java 代码 package com.lizhouwei.chapter7;/*** @Description: 在其他数都出现k 次的数组中找 ...
- 《程序员代码面试指南》第二章 链表问题 搜索二叉树转换为双向链表
样例 树的中序遍历:1 2 3 4 5 6 7 ,转换后双向链表的遍历:1 2 3 4 5 6 7 java代码 /*** @Description:搜索二叉树转换为双向链表* @Author: li ...
- 《程序员代码面试指南》第八章 数组和矩阵问题 在行列都排好序的矩阵中找数...
题目 在行列都排好序的矩阵中找数 java代码 package com.lizhouwei;/*** @Description: 在行列都排好序的矩阵中找数* @Author: lizhouwei* ...
最新文章
- NineImageForCircleFriends朋友圈九宫格
- 使用netfilter框架处理ARP报文
- 使用OpenCV-python实现手写数字识别
- 二叉搜索树第k小元素
- Riemann映射定理
- VMware Funsion 修改vmnet1/vmnet8默认网络地址及DHCP地址
- cloudera-scm-service报错server已死,但pid文件仍存问题解决
- Java Eclipse下载安装教程
- 深度学习?不一定非得搞“黑箱”
- 模拟量输入输出配置及数值的规范化
- 通过aosp-latest下载Android源码
- ppt怎么把图片做成翻书效果_如何用PPT实现翻书效果?
- 微信小程序 之wxml保留小数点后两位数的方法及转化为字符串的方法
- 即将迎接我们的 3D 音频以及全新的虚拟现实(下)
- linux 定时开关机
- 学生HTML个人网页作业作品~个人主页博客网页设计制作(6个页面)~大学生个人网站作业模板~HTML简单个人网页制作
- linux c 读取u盘mbr,fbinst 启动U盘解读(MBR层面)
- 圣诞来袭,学编程的小伙伴收到圣诞老人礼物了?
- 用顺序表求集合的交集、并集和差集
- 字符串匹配的三种算法