剑指offer
来源:互联网 发布:手机铃声编辑软件 编辑:程序博客网 时间:2024/06/18 07:14
15 链表中倒数第k个结点
是否环形链表
假设存在两个指针*a,*b都指向链表的头结点,每循环判断一次,a向前走一步,b向前走两步。那么如果这样算下去,总有一个有限循环内,b会到达NULL指针或者b和a相等。此时停止循环。
//判断链表是否存在环 public class Solution { public boolean hasCycle(ListNode head) { if (head == null) return false; ListNode first = head, second = head; while (first != null && first.next != null) { first = first.next.next; second = second.next; if (first == second) return true; } return false; }}
16 反转链表
//递归方式Node * reverseList(List head){ //如果链表为空或者链表中只有一个元素 if(head == NULL || head->next == NULL) { return head; } else { //先反转后面的链表,走到链表的末端结点 Node *newhead = reverseList(head->next); //再将当前节点设置为后面节点的后续节点 head->next->next = head; head->next = NULL; return newhead; }}
19 二叉树的镜像
//递归方式public void mirror(Node root) { if (root == null || (root.left == null && root.right == null)) return; Node temp = root.left; root.left = root.right; root.right = temp; if (root.left != null) mirror(root.left); if (root.right != null) mirror(root.right);}
//非递归方式public void mirror(Node root) { if (root == null || (root.left == null && root.right == null)) return; LinkedList<Node> list = new LinkedList<>(); list.addFirst(root); Node temp = null; Node current = null; while (!list.isEmpty()) { current = list.removeFirst(); if (current.left != null || current.right != null) { temp = current.left; current.left = current.right; current.right = temp; } if (current.left != null) list.addFirst(current.left); if (current.right != null) list.addFirst(current.right); }}
26 复杂链表的复制
分为三步,第一步把原链表的每个节点都复制一个,并放在原每个节点后面;第二步,设置另一个指针;第三步,拆分两个链表
牛客上没有通过
/*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) { if (pHead != null) { copyNode(pHead); copyRandom(pHead); return split(pHead); } return null; } private void copyNode(RandomListNode pHead) { while (pHead != null) { RandomListNode n = new RandomListNode(pHead.label); n.next = pHead.next; pHead.next = n; pHead = n.next; } } private void copyRandom(RandomListNode pHead) { while (pHead != null) { RandomListNode n = pHead.next; n.random = pHead.random.next; pHead = n.next; } } private RandomListNode split(RandomListNode pHead) { RandomListNode n = pHead.next; pHead = n; while (pHead.next != null) { pHead.next = pHead.next.next; pHead = pHead.next; } return n; }}
27 二叉树转双向链表
由于二叉搜索树的中序遍历是递增序列,所以这个题考虑用中序遍历的方式。二叉树的根节点需要和左子树最大的一个节点相连,同时也需要和右子树最大的一个节点相连。所以需要一个指针依次指向二叉树的左节点、根节点和右节点。当这个指针指向左节点时,由于递归会使得栈里的“指针”指向根节点,因为此时左节点是叶子节点,所以递归会return到根节点;然后就可以让这个指向左节点的指针和指向根节点的“指针”完成互相指向的操作,即左节点右边是根节点,根节点左边是左节点。然后当前节点指向根节点,递归去做右子树的转化操作。
/**public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; }}*/public class Solution { public TreeNode current = null; public TreeNode head = null; public TreeNode Convert(TreeNode pRootOfTree) { convertNode(pRootOfTree); return head; } public void convertNode(TreeNode root) { if (root == null) return; convertNode(root.left); if (current == null) { //初始化 current = root; head = root; } else { current.right = root; root.left = current; current = root; } convertNode(root.right); }}
28 字符串的全排列
主要是通过交换字符的位置完成排列,假设原字符串为abc
a不交换位置,即相当于a与a交换位置,这时固定好a,后面的bc然后重复这一过程,很明显,这是一个递归的思路。这完成了由a打头的所有字符串的排列。
a与b交换位置,字符串变为bac。同理,这将完成所有由b打头的字符串的排列。
a与c交换位置,这将完成所有由c打头的字符串的排列。
import java.util.*;public class Solution { public List<String> permutation(String str) { List<String> list = new ArrayList<>(); if (str != null && str.length() > 0) { permutation(str.toCharArray(), 0, list); Collections.sort(list); } return list; } private void permutation(char[] arr, int index, List<String> list) { if (index == arr.length - 1) { list.add(String.valueOf(arr)); } else { for (int i = index; i < arr.length; i++) { if (i == index || arr[i] != arr[index]) { swap(arr, i, index); permutation(arr, index + 1, list); swap(arr, i, index); } } } } private void swap(char[] arr, int i, int j) { char tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }}
29 数组中出现次数超过一半的数字
使用HashMap存储数字和出现的次数。注意数组只有一个元素时这样的边界条件。
30 最小的k个数
1. 使用最大堆,自己写堆排序的代码
2. 使用TreeMap,基于红黑树,查找、插入和删除时间都是logN。使用TreeMap的lastKey方法。因为红黑树是二叉查找树,只要比最大的小就ok。
- 剑指OFFER
- 剑指offer
- 剑指Offer
- 剑指offer
- 剑指Offer
- 剑指offer
- 剑指offer
- 剑指offer
- 剑指Offer
- 剑指offer
- 剑指offer
- 剑指Offer
- 剑指offer
- 剑指offer
- 《剑指offer》
- 剑指Offer
- 剑指offer
- 剑指offer
- iOS开发系列--让你的应用“动”起来
- loopup第二篇:在salesforce中实现跨对象查询过滤与父查询相关的子对象的值
- vs2010 搭建驱动开发环境
- JavaWeb过滤器的高级配置
- 链接字符
- 剑指offer
- 将python服务器搭载云上,以及配置java环境
- mongoDB数据的导出导入
- 静态查找-哨兵
- Win7系统中wmiprvse.exe占用CPU高如何解决
- 利用百度Echart库,完成简单迁徙图
- Java输入输出流
- Android定位服务
- Ubuntu 使用C++ ORM框架--ODB