题一:【复杂链表的复制】
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
分析:复制一个链表,则需要复制链表中的每一个节点和节点之间的关系,而不只是只复制一个头节点直接引用那么简单。
1 /* 2 public class RandomListNode { 3 int label; 4 RandomListNode next = null; 5 RandomListNode random = null; 6 7 RandomListNode(int label) { 8 this.label = label; 9 } 10 } 11 */ 12 public class Solution { 13 public RandomListNode Clone(RandomListNode pHead) 14 { 15 if(pHead==null) return null; 16 RandomListNode head = pHead; 17 //1.在旧链表中创建新链表,此时不处理新链表的兄弟节点 18 while(head!=null){ 19 RandomListNode node = new RandomListNode(head.label);//复制链表的结点 20 node.next = head.next; 21 head.next = node; 22 head = head.next.next; 23 } 24 //2.根据旧链表的兄弟节点,初始化新链表的兄弟节点random 25 head = pHead;//此时head是原来链表和复制后的链表集合 26 while(head!=null){ 27 RandomListNode node = head.next; 28 if(head.random!=null){ 29 node.random = head.random.next; 30 } 31 head = head.next.next; 32 } 33 //3.从旧链表中拆分得到新链表 34 head = pHead; 35 RandomListNode newHead = head.next; 36 while(head!=null){ 37 RandomListNode node = head.next; 38 head.next = node.next; 39 if(node.next!=null){ 40 node.next = node.next.next; 41 } 42 head = head.next; 43 } 44 return newHead; 45 } 46 }
题二:【二叉搜索树与双向链表】
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
分析:中序遍历,先将遍历的节点添加进一个列表中,再重新节点索引。
1 import java.util.ArrayList; 2 /** 3 public class TreeNode { 4 int val = 0; 5 TreeNode left = null; 6 TreeNode right = null; 7 8 public TreeNode(int val) { 9 this.val = val; 10 11 } 12 13 } 14 */ 15 public class Solution { 16 ArrayList<TreeNode> list = new ArrayList<TreeNode>(); 17 public TreeNode Convert(TreeNode pRootOfTree) { 18 if(pRootOfTree==null) return null; 19 helpConvert(pRootOfTree); 20 sort(list); 21 return list.get(0); 22 } 23 public void helpConvert(TreeNode pRootOfTree){ 24 if(pRootOfTree==null) return; 25 helpConvert(pRootOfTree.left); 26 list.add(pRootOfTree); 27 helpConvert(pRootOfTree.right); 28 } 29 public void sort(ArrayList<TreeNode> list){ 30 for(int i=0;i<list.size()-1;i++){ 31 list.get(i).right = list.get(i + 1); 32 list.get(i + 1).left = list.get(i); 33 } 34 } 35 }
题三:【字符串的排列】
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。(输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。)
分析:使用递归。每次将当前索引处字符和后边字符轮流交换,例如i=0,j=i,j++时,字符a轮流后bcde交换。每次交换之后递归字串,例如a和b交换后变成bacde,再递归acde,以此类推。直到当i=4时,递归结束,将此时字符添加进列表中。
【注意1】每次递归前swap交换字符,递归后要复位,再进行一次swap,例如ab cde(空格忽略,此处为标识),此时交换cc、cd、ce,若进行到交换cd时,此时字符串为ab dce,若abd ce(字串)递归完成,要将cd再次交换成ab cde,进行ce的交换递归。
【注意2】
import java.util.*; public class Solution { public ArrayList<String> Permutation(String str) { ArrayList<String> list = new ArrayList<String>(); char[] arr = str.toCharArray(); if(str.length()>0&&str!=null){ Permutation(arr, 0, list); Collections.sort(list); } return list; } public void Permutation(char[] arr, int i, ArrayList<String> list){ if(i==arr.length-1){ list.add(String.valueOf(arr)); }else{ for(int j=i;j<arr.length;j++) { if(!(arr[i]==arr[j]&&i!=j)) //此处防止重复字符 { swap(arr,i,j); Permutation(arr,i+1,list); swap(arr,i,j); } } } } public void swap(char[] arr, int i, int j){ char tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } }