CodeTop刷题记录-京东(1)
创始人
2024-06-02 01:50:08
0
  1. 环形链表 II 206. 反转链表 912. 排序数组

大家好,文章题目是codeTop上的热门题目,本文章是京东面试题目热门题目。虽然算法在后端日常开发中应用比较少,但是它对思维的开发是很有益的,也是进中、大厂的必备的东西。文章致力于用最简单的语言阐述解题思路和解题方法,欢迎大家讨论更优秀的解题方案。

ps:对题目的讲解分为三部分,题意描述、思路描述和代码编写。众所周知有思路不一定能编写出代码,思路的完整性有助于一次AC。

强烈建议参考代码一起思考,有些东西用语言表达不出来,也就是脑子会了,手不会。题解地址

题目

142. 环形链表 II

题意:

给出一个链表,链表包含本身数值和下一个数据的地址。需要判断出此链表存不存在环形结构,返回入环的节点。

思路:

若链表有环,那么循环链表的话会永远找不到出口,可以利用这个特性,就像人在操场跑步,只要第一名足够快,第一名和最后一名一定会相遇,在链表中循环也是一样利用套圈会相遇的特点,使用两个循环若相遇(相同值)就是有环,否则无环。

但是有个问题,虽然能相遇,但是不一定是在开始循环的节点相遇,还需要计算出入环节点。

这个时候就需要公式推导了(为什么公式可以推导?因为这个是有规律的)
我们称快的为fast,慢的为slow。为了好计算,fast的速度是2,slow为1,即fast一次循环两个节点,slow为一个。

  • 以路程为视角,S(fast) = 2S(slow)
  • 以fast追slow为视角,追了n圈才相遇,S(fast)=S(slow) + n * S(环长度)
  • 得出S(slow) = n * S(环长度)
  • 以slow为视角,S(slow) = res + m * S(环长度)

res为从起点到入环的距离,即slow再走res步就是答案。换个说法,从head走res步也是入环节点,那么从head和slow位置同时走,走res步则会相遇,只要判断相遇,相遇的点就是入环点,就是答案。

代码解析:

有了思路,剩下的是转换为代码,参考

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;public class Main {public static void main(String[] args) {ListNode listNode1 = new ListNode(3);ListNode listNode2 = new ListNode(2);ListNode listNode3 = new ListNode(0);ListNode listNode4 = new ListNode(-4);listNode1.next = listNode2;listNode2.next = listNode3;listNode3.next = listNode4;listNode4.next = listNode2;ListNode res1 = detectCycle1(listNode1);System.out.println(res1.val);ListNode res2 = detectCycle2(listNode1);System.out.println(res2.val);}/*** 哈希法判断* 利用哈希表进行判断是是否存在此节点来判断是否存在环形* 每次循环时,首先判断是否在Set中* - 若不存在则加入到Set中* - 若存在则返回节点* - 若节点为空,返回空* 

* 复杂度分析:O(N) O(N)** @param head 链表* @return 结果*/public static ListNode detectCycle1(ListNode head) {Set nodeSet = new HashSet<>();while (true) {if (head == null) {return null;}if (nodeSet.contains(head)) {return head;}nodeSet.add(head);head = head.next;}}/*** 双指针* AB两指针分别一次走2和1的距离,因为有距离差,若存在环形结构,一定会被套圈追上* 首先计算出相遇的位置,这个位置可以用公式表示(起点到环形距离为lenA,环形长度为lenB):* ∵ A走的速度快* ∴ Sa = 2 * Sb(A走过的距离=2*B走过的距离)* ∵ A走的多,在追B时,多走了很多圈* ∴ Sa = Sb + n * lenB* 整合后* ∴ Sb = n * lenB Sa = 2 * n * lenB* 所以AB走的距离都可以用lenB表示。*

* 若从起点出发,最终停留在循环入口处,期间转了m圈用公式表示:* Res = lenA + m * lenB ①* ∵ n m 都是基于链表的实际数字,圈数与位置没有关系* ∵ Sb停留的位置一定在环上,但不一定在起点处,结合上面公式①* ∴ Sb + lenA 的位置一定是起点,也就是结果*

* 当B走lenA后,即为答案,问题转换为求lenA* Sb = n * lenB* 令Sa = 0* 当Sa = lenA时,Sb = lenA + n * lenB** @param head 链表* @return 结果*/public static ListNode detectCycle2(ListNode head) {ListNode fast = head;ListNode slow = head;while (true) {// 无环退出if (fast == null || fast.next == null) {return null;}// 走一次两个距离fast = fast.next.next;// 走一次一个距离slow = slow.next;// 相遇退出if (fast == slow) {break;}}// 最后一步,相遇即可fast = head;while (fast != slow) {fast = fast.next;slow = slow.next;}return fast;}static class ListNode {int val;ListNode next;ListNode(int x) {val = x;next = null;}} }

206. 反转链表

题意:

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

思路:

既然是链表,进行循环即可,因为需要反向输出,循环的第一个节点就是最后一个节点,每次循环时,新建一个节点,使此节点的next指针指向循环节点的值。

题外话:程序是一个呆板的、写死的、只能按照预先设置好的执行,所以思考时需要往通用型方向思考,特殊情况特殊判断,即可完成一个健壮性程序。

代码解析:

public class ReverseList {/*** 题意:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。* 思路:既然是链表,进行循环即可,因为需要反向输出,循环的第一个节点就是最后一个节点,每次循环时,新建一个节点,使此节点的next指针指向循环节点的值。** @param args arg*/public static void main(String[] args) {ListNode listNode1 = new ListNode(1);ListNode listNode2 = new ListNode(2);ListNode listNode3 = new ListNode(3);ListNode listNode4 = new ListNode(4);listNode1.next = listNode2;listNode2.next = listNode3;listNode3.next = listNode4;ListNode res = reverseList(listNode1);while (res != null) {System.out.print(res.val + " ");res = res.next;}}public static ListNode reverseList(ListNode head) {// 结果链表ListNode res = new ListNode();// 第一个节点特殊判断,作为新链表最后一个节点的值if (head != null) {res.val = head.val;} else {return null;}while (true) {if (head.next != null) {head = head.next;// 新节点作为父节点,t一直为循环至此的,结果的,第一个节点ListNode t = new ListNode();t.val = head.val;t.next = res;// res替换为新的第一个节点res = t;} else {break;}}return res;}static class ListNode {int val;ListNode next;ListNode() {}ListNode(int val) {this.val = val;}ListNode(int val, ListNode next) {this.val = val;this.next = next;}}
}

912. 排序数组

题意:

给你一个整数数组 nums,请你将该数组升序排列。

思路:

快速排序。
快速排序是采用二分的思维方式,选中数组中的一个数字,以它为标准,左放比它小的数字,右边放大于它的数字,那么这个数字的位置就可以确定了,然后左边的数字、右边的数字重复这一操作,最终排序的数组为一个数字,那么排序也就完成了。
即每次只排一个数字。
优化:选取数字标准的时候,可以从数组中随机挑取,这样会加快排序速度。

代码解析:

import java.util.Arrays;
import java.util.Random;public class QuickSort {private static final Random RANDOM = new Random();/*** 题意:给你一个整数数组 nums,请你将该数组升序排列。* 解析:快速排序。* 快速排序是采用二分的思维方式,选中数组中的一个数字,以它为标准,左放比它小的数字,右边放大于它的数字,那么这个数字的位置就可以确定了,然后左边的数字、右边的数字重复这一操作,最终排序的数组为一个数字,那么排序也就完成了。* 即每次只排一个数字。* 优化:选取数字标准的时候,可以从数组中随机挑取,这样会加快排序速度。** @param args arg*/public static void main(String[] args) {int[] nums = new int[]{5, 1, 1, 2, 0, 0};int[] ints = sortArray(nums);System.out.println(Arrays.toString(ints));}public static int[] sortArray(int[] nums) {// 快速排序return quickSort(nums);}/*** 快速排序** @param nums 数组* @return 结果*/private static int[] quickSort(int[] nums) {// 递归处理quickSortFun(nums, 0, nums.length - 1);return nums;}private static void quickSortFun(int[] nums, int left, int right) {// left,right分表代表着需要排序数组的区间,若不满足下属要求,说明已经不需要排序了if (left >= right) {return;}// 从数组中随机挑取一个数组与最左边的数字交换,即最左边为此次排序的标准int randomIndex = left + RANDOM.nextInt(right - left + 1);swap(nums, randomIndex, left);// 为何+1,是因为left数字为此次排序标准数,不参与排序,只需要最后放到它应该在的地方即可int i = left + 1;int j = right;int index = nums[left];while (true) {// 从左到右,比标准数小的话直接跳过,相等是不跳过的(原因如下),i是可以到达right的,while (i <= right && nums[i] < index) {i++;}// 从右到左,比标注数大的话直接跳过,相等是不跳过的(原因如下),j不允许到达leftwhile (j > left && nums[j] > index) {j--;}// 限制左右循环不允许相遇(相遇说明排序完成了)if (i >= j) {break;}// i,j分别停留在了大于、小于标准数的位置,交换两个数字使数组满足要求// 相等的元素通过交换,等概率分到数组的两边swap(nums, i, j);i++;j--;}// 最终停留位置与标准数交换,那么标准数已经放到最终位置swap(nums, left, j);quickSortFun(nums, left, j - 1);quickSortFun(nums, j + 1, right);}private static void swap(int[] nums, int index1, int index2) {int temp = nums[index1];nums[index1] = nums[index2];nums[index2] = temp;}
}

相关内容

热门资讯

曾经的爱 曾经的爱我自己来回答我可能是真的喜欢她但是,每次不知道为什么看到她就一中伤心的感觉不知道谁能告诉我这...
小公鸡不见偷偷的跟在小鸭子后面... 小公鸡不见偷偷的跟在小鸭子后面也下了水偷偷地这个词加上这个词的好处是小公鸡不见偷偷的跟在小鸭子后面也...
开紫钻一年多少钱? 开紫钻一年多少钱?我卖180 ,一年大概120 玩旋舞特适合用财富通开8.8折一共是211
关于韩剧 关于韩剧灰姑娘的姐姐吧,不错。还有一枝梅。狗与狼的时间,都好看。
谁小泰罗的电影? 谁小泰罗的电影?小泰罗奥特曼的电影? 你说的这个是奥特曼剧场版《奥特物语》网上搜一下就能找到
电纸书和mp4功能一样吗,买电... 电纸书和mp4功能一样吗,买电子书好还是mp4好啊?推荐一款吧?谢谢看你具体干什么了,如果喜欢看电子...
关于ff14的装备出售问题! ... 关于ff14的装备出售问题! 为什么好多装备无法在市场出售?紫装绿装不说,为什么普通白装也不能关于f...
为什么佛法的争论那么激烈? 为什么佛法的争论那么激烈?因为他们没有一个统一的经典,来指导他们,告诉他们真理. 不然他们就不会拜那...
为什么有的调皮美女不喜欢调皮男... 为什么有的调皮美女不喜欢调皮男人,不稳重没有安全感。她喜欢成熟有男人味安全感男人?大部分女人都喜欢成...
哪些男明星男人味儿彰显,成熟的... 哪些男明星男人味儿彰显,成熟的魅力撩动心弦让你沦陷?朱一龙,张若昀,李钟硕,李承铉,靳东等,这些男明...
天书奇谈里皇城里的盘龙石柱在哪... 天书奇谈里皇城里的盘龙石柱在哪阿、?点左上角的【寻】会出来一个框,里面有蟠龙石柱,点击左键会自动寻找...
50年前,长沙镖子岭。老烟头把... 50年前,长沙镖子岭。老烟头把他的旱烟在地上敲了敲:“下不下去喃?”独眼的小伙子说:“不去,电视剧5...
如何评价演员袁姗姗,她是不是真... 如何评价演员袁姗姗,她是不是真的不适合娱乐圈?因人而异吧,我个人还是比较喜欢她的,虽然长得确实不漂亮...
各路大神? 各路大神?既然可以发送、接受文件,可以确认电脑蓝牙驱动正常,可以连接手机蓝牙。接下来要确认手机有蓝牙...
三国演义诸葛亮的资料 三国演义诸葛亮的资料三国演义诸葛亮的资料去看史书就知道了诸葛亮子孔明,号卧龙,南阳人,著作出师表,隆...
如何隐藏一个硬盘分区,只能我自... 如何隐藏一个硬盘分区,只能我自己能进,别人都看不到。用patition magic 隐藏分区
韩剧名字其中两个字是爱情 韩剧名字其中两个字是爱情没关系,是爱情啊--赵寅成,孔孝真最佳爱情--车胜元,孔孝真爱情能用钱买吗-...
谁炒股一年能挣百万 谁炒股一年能挣百万规定时间 数量 你以为在算加减法 能有正解答案 股市是有时长时短 时多时少 这是没...
一个你不爱的人 一个你不爱的人面拒绝 呵呵,女的都出来了,这问题到是比较符合你们!其他的怎么女的回答的那么少??
有人有曲的成语 有人有曲的成语曲尽人情【读音】qū jìn rén qíng【释义】委婉周到地把人之常情或世态充分体...