目录
17.电话号码的组合
思路:
首先使用哈希表存储每个数字对应的所有可能的字母,然后进行回溯操作。每次取电话号码的一位数字,从哈希表中获得该数字对应的所有可能的字母,并将其中的一个字母插入到已有的字母排列后面,然后继续处理电话号码的后一位数字,直到到达最后一个数字,即得到一个完整的字母排列。然后进行回退操作,遍历其余的字母排列。
代码:
public static List<String> letterCombinations(String digits) {
//存储最终的结果
List<String> combinations = new ArrayList<String>();
//如果输入的为空
if (digits.length() == 0) {
return combinations;
}
//用HashMap存储数字以及对应的字母
Map<Character, String> phoneMap = new HashMap<Character, String>() {{
put('2', "abc");
put('3', "def");
put('4', "ghi");
put('5', "jkl");
put('6', "mno");
put('7', "pqrs");
put('8', "tuv");
put('9', "wxyz");
}};
backtrack(combinations, phoneMap, digits, 0, new StringBuffer());
return combinations;
}
//回溯函数
public static void backtrack(List<String> combinations, Map<Character, String> phoneMap, String digits, int index, StringBuffer combination) {
//如果到达末尾,则将这个字符串添加到最终结果中,并回溯
if (index == digits.length()) {
combinations.add(combination.toString());
} else {
//获取当前的数字
char digit = digits.charAt(index);
//获取数字对应的字符串
String letters = phoneMap.get(digit);
//获取字符串的长度
int lettersCount = letters.length();
//遍历
for (int i = 0; i < lettersCount; i++) {
//添加第一个字符
combination.append(letters.charAt(i));
//递归进入最后一个字符
backtrack(combinations, phoneMap, digits, index + 1, combination);
//用combination临时存储,当递归进入到最后一个数字时,就会将字符串添加到combinations中,因此,下次
//再使用时,要将combination中存储的内容删除
combination.deleteCharAt(index);
}
}
}
19.删除链表的倒数第N个节点
解法一:栈
思路:
节点依次入栈。根据栈「先进后出」的原则,我们弹出栈的第n 个节点就是需要删除的节点,并且目前栈顶的节点就是待删除节点的前驱节点。只需要前驱节点指向它下一个的下一个结点即可。
代码:
public ListNode removeNthFromEnd(ListNode head, int n) {
//具有虚拟头结点的链表dummy,防止出现删除第一个结点要分别讨论的情况
ListNode dummy = new ListNode(-1, head);
//栈
Stack<ListNode> stack = new Stack<>();
//当前指针
ListNode cur = dummy;
//结点依次入栈
while (cur != null) {
stack.push(cur);
cur = cur.next;
}
//依次弹栈
for (int i = 0; i < n; ++i) {
stack.pop();
}
//指向顶峰的结点
ListNode prev = stack.peek();
//跳过要删除的那个结点
prev.next = prev.next.next;
//跳过虚拟头结点
ListNode ans = dummy.next;
return ans;
}
解法二:list存储结点
思路:
用list依次存储结点,然后删除倒数第n个元素,将剩余的元素用头插法重新建立链表。
代码:
public ListNode removeNthFromEnd (ListNode head, int n) {
ArrayList<Integer> list = new ArrayList<>();
if (head == null) {
return null;
}
//结点依次存入list
while (head != null) {
list.add(head.val);
head = head.next;
}
//删除倒数第n个结点
list.remove(list.size() - n);
//如果恰好有一个,并且已经删除,返回null
if (list.isEmpty()) {
return null;
}
//尾插法建立链表
ListNode newHead = new ListNode(list.get(0));
ListNode cur = newHead;
for (int i = 1; i < list.size(); i++) {
cur.next = new ListNode(list.get(i));
cur = cur.next;
}
return newHead;
}