nowcoder-oj【面试高频TOP榜单-简单难度(5)5道】
1、NC96 判断一个链表是否为回文结构
import java.util.*; /* * public class ListNode { * int val; * ListNode next = null; * } */ public class Solution { /** * * @param head ListNode类 the head * @return bool布尔型 */ public boolean isPail (ListNode head) { // write code here } }
实现
/* * public class ListNode { * int val; * ListNode next = null; * } */ import java.util.*; public class Solution { /** * * @param head ListNode类 the head * @return bool布尔型 */ //未完成:11/13 组用例通过 public boolean isPail (ListNode head) { if(head == null){ return false; } if(head.next == null){ return true; } //思路:遍历单链表,将所有节点的数据存入一个数组/列表,遍历前一半列表,对比后一半中对应位置的数值是否一致 ArrayList<Integer> list = new ArrayList<>(); while(head != null){ list.add(head.val); head = head.next; } int len = list.size(); // if(len % 2 == 0){ //偶数个元素 // }else{ //奇数个元素(中间元素不需要参与遍历对比) // } //经过推导发现:以下遍历可以解决奇偶数问题(即i<len/2可以避开奇数列表中的最中间元素) for(int i=0; i<len/2; i++){ if(list.get(i) != list.get(len-i-1)){ //推导出后半段回文对应位置下标为len-i-1 return false; } } return true; } }
参考
【数据结构和算法】判断回文链表,图文详解_牛客博客 (nowcoder.net)
//思路:快慢指针找到单链表的“中间节点”,反转后半部分链表,同步遍历两个小链表,对比对应节点的值 import java.util.*; public class Solution { public boolean isPail (ListNode head) { //通过快慢指针找到中点 ListNode fast = head, slow = head; while(fast != null && fast.next != null){ fast = fast.next.next; slow = slow.next; } //如果fast不为空,说明链表的长度是奇数个 if(fast != null){ slow = slow.next; } //反转后半部分链表 slow = reverse(slow); //前半小链表(逻辑上是两个小链表,其实fast还是原链表但我们只需要其前一半,后半部分是名副其实的反转构造的小链表) fast = head; //遍历,比较对应节点值是否相等 while(slow != null){ if(fast.val != slow.val){ return false; }else{ fast = fast.next; slow = slow.next; } } return true; } public ListNode reverse(ListNode head) { ListNode prev = null; while (head != null) { ListNode temp = head.next; head.next = prev; prev = head; head = temp; } return prev; } }
2、NC34 求路径
import java.util.*; public class Solution { /** * * @param m int整型 * @param n int整型 * @return int整型 */ public int uniquePaths (int m, int n) { // write code here } }
参考
//参考1 public int uniquePaths (int m, int n) { int[][] dp = new int[m+1][n+1]; for(int i=1; i<=m; i++){ //第一列赋值为1 dp[i][1] = 1; } for(int j=1; j<=n; j++){ //第一行赋值为1 dp[1][j] = 1; } for(int i=2; i<=m; i++){ for(int j=2; j<=n; j++){ dp[i][j] = dp[i-1][j] + dp[i][j-1]; } } return dp[m][n]; }
//参考2 public int uniquePaths (int m, int n) { int N = n+m-2; int K = n-1; double num = 1.0; for(int i=1; i<=K; i++){ num = num * (N-K+i) / i; } return (int)num; }
3、NC57 反转数字
import java.util.*; public class Solution { /** * * @param x int整型 * @return int整型 */ public int reverse (int x) { // write code here } }
实现
//19/20 组用例通过 //java.lang.NumberFormatException: For input string: "9876543212" public int reverse (int x) { boolean flag; if(x < 0){ flag = false; }else{ flag = true; } if(!flag){ x = -x; } //不论原始输入的x是正数还是负数,此时x是正数 String strX = String.valueOf(x); StringBuffer sb = new StringBuffer(strX); String revStrX = sb.reverse().toString(); int res = Integer.parseInt(revStrX); if(!flag){ res = -res; } //左移:num << n,相当于num乘以2的n次方 //右移:num >> n,相当于num除以2的n次方 //2的32次方,相当于32个2相乘,就是1乘以32个2,1<<32 // int temp = 1 << 32; //1,没生效?? if(res < -Math.pow(2,31) || res > Math.pow(2,31)-1){ return 0; } return res; }
参考
【数据结构和算法】反转数字,图文详解_牛客博客 (nowcoder.net)
public int reverse(int x) { int res = 0; while (x != 0) { int t = x % 10; int newRes = res * 10 + t; //如果数字溢出,直接返回0 if ((newRes - t) / 10 != res) return 0; res = newRes; x = x / 10; } return res; }
public int reverse(int x) { long res = 0; while (x != 0) { res = res * 10 + x % 10; x /= 10; } return (int) res == res ? (int) res : 0; }
4、NC16 判断二叉树是否对称
import java.util.*; /* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * } */ public class Solution { /** * * @param root TreeNode类 * @return bool布尔型 */ public boolean isSymmetric (TreeNode root) { // write code here } }
参考1
判断二叉树是否对称【递归】【迭代】详解!_牛客博客 (nowcoder.net)
参考2
【数据结构和算法】递归和非递归两种方式解决_牛客博客 (nowcoder.net)
import java.util.*; public class Solution { public boolean isSymmetric (TreeNode root) { if (root == null){ return true; } return isSymmetricHelper(root.left, root.right); //从两个子节点开始判断 } public boolean isSymmetricHelper(TreeNode leftTree, TreeNode rightTree) { if (leftTree == null && rightTree == null){ //如果左右子节点都为空,说明当前节点是叶子节点,返回true return true; } if (leftTree == null || rightTree == null || leftTree.val != rightTree.val){ //如果当前节点只有一个子节点或者有两个子节点,但两个子节点的值不相同,直接返回false return false; } //然后左子节点的左子节点和右子节点的右子节点比较,左子节点的右子节点和右子节点的左子节点比较 return isSymmetricHelper(leftTree.left, rightTree.right) && isSymmetricHelper(leftTree.right, rightTree.left); } }
import java.util.*; public class Solution { public boolean isSymmetric (TreeNode root) { if (root == null){ return true; } Queue<TreeNode> queue = new LinkedList<>(); //队列 //左子节点和右子节点同时入队 queue.add(root.left); queue.add(root.right); //如果队列不为空就继续循环 while (!queue.isEmpty()) { //每两个出队 TreeNode left = queue.poll(), right = queue.poll(); //如果都为空继续循环 if (left == null && right == null){ continue; } //如果一个为空一个不为空,说明不是对称的,直接返回false if (left == null ^ right == null){ return false; } //如果这两个值不相同,也不是对称的,直接返回false if (left.val != right.val){ return false; } //这里要记住入队的顺序,他会每两个两个的出队。 //左子节点的左子节点和右子节点的右子节点同时 //入队,因为他俩会同时比较。 //左子节点的右子节点和右子节点的左子节点同时入队, //因为他俩会同时比较 queue.add(left.left); queue.add(right.right); queue.add(left.right); queue.add(right.left); } return true; } }
5、NC25 删除有序链表中重复的元素
import java.util.*; /* * public class ListNode { * int val; * ListNode next = null; * } */ public class Solution { /** * * @param head ListNode类 * @return ListNode类 */ public ListNode deleteDuplicates (ListNode head) { // write code here } }
实现
import java.util.*; public class Solution { public ListNode deleteDuplicates (ListNode head) { if(head == null || head.next == null){ return head; } TreeSet<Integer> set = new TreeSet<>(); while(head != null){ set.add(head.val); head = head.next; } ListNode res = new ListNode(-1); //头结点不能为空,因为null.next报空指针,-1不属于结果仅占位用 ListNode move = res; for(int num: set){ ListNode temp = new ListNode(num); move.next = temp; move = move.next; } return res.next; } }
其他1
import java.util.*; public class Solution { public ListNode deleteDuplicates (ListNode head) { if (head == null){ return head; } // a-b-c,三个位置使用三个指针 // 如果 b=c,删除b就可以 // 创建一个虚拟头部 ListNode visual = new ListNode(-1); visual.next = head; ListNode first = visual; ListNode second = head; ListNode third = head.next; while (third!=null){ //相等就进行处理 if (second.val == third.val){ first.next = third; second = third; third = third.next; } else { // 不相等就继续遍历 first = second; second = third; third = third.next; } } return visual.next; } }
其他2
import java.util.*; class Solution { public ListNode deleteDuplicates(ListNode head) { ListNode dummy = new ListNode(Integer.MAX_VALUE); dummy.next = head; ListNode cur = dummy; while (cur.next != null && cur.next.next != null) { if (cur.next.val == cur.next.next.val) { cur.next = cur.next.next; } else { cur = cur.next; } } return dummy.next; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!