1.连接两个有序链表
//将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 // // // // 示例: // // 输入:1->2->4, 1->3->4 //输出:1->1->2->3->4->4 // // Related Topics 链表
第一次接触到链表,我个人觉得链表构成最重要的就是指向,不要把两个链表看成是两个独立的数组一样的东西,而是需要懂得通过建立关联,只要改变指向,马上可以生成新的链表。而且注意我们的函数是对两个节点进行操作,所以完成的时候要更多的有点的意识,最后的返回值返回的也是头结点,整个函数只是对链表的指向进行了更改。主要有两种方法,一种是迭代法,一种是递归法。迭代法的思路就是设置一个哑结点来作为隐形的头结点,然后依次指向val较大的节点。递归法是比较得出val最小的节点,然后用其指向较大的节点,其中函数自身调用自身,不断选中大的节点。对于尾结点的处理方式,都是判断其中一个的是否遍历完,如果是,那就连接下一个的节点就行。讲的不太清楚,看代码就很清楚了。
public class P21MergeTwoSortedLists{
public static void main(String[] args) {
Solution solution = new P21MergeTwoSortedLists().new Solution();
// TO TEST
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
node1.next = node3;
node3.next = node5;
node5.next = null;
node2.next = node4;
node4.next = null;
//注意:这里返回的都是头结点,我们的函数只是改变了指针的指向
ListNode node = solution.mergeTwoLists(node1, node2);
while (node != null){
System.out.print(node.val);
node = node.next;
}
}
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//是可以和链表分开存在的,只要改变指向,就能形成一个新的链表,而且这里的改变指向只是为了更好的比较
/*if(l1==null){
return l2;
}else if(l2 == null){
return l1;
}else if(l1.val < l2.val){
l1.next = mergeTwoLists(l1.next, l2);
return l1;
}else{
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}*/
ListNode prehead = new ListNode(-1);
ListNode prev = prehead;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
prev.next = l1;
l1 = l1.next;
} else {
prev.next = l2;
l2 = l2.next;
}
prev = prev.next;
}
// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev.next = l1 == null ? l2 : l1;
return prehead.next;
}
}
//leetcode submit region end(Prohibit modification and deletion)
}
/**
* Definition for singly-linked list.*/
class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
2.去除数组中重复的元素
//给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 // // 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 // // // // 示例 1: // // 给定数组 nums = [1,1,2], // //函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 // //你不需要考虑数组中超出新长度后面的元素。 // // 示例 2: // // 给定 nums = [0,0,1,1,1,2,2,3,3,4], // //函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。 // //你不需要考虑数组中超出新长度后面的元素。 // // // // // 说明: // // 为什么返回数值是整数,但输出的答案是数组呢? // // 请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。 // // 你可以想象内部操作如下: // // // nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝 //int len = removeDuplicates(nums); // 在函数里修改输入数组对于调用者是可见的。 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。 //for (int i = 0; i < len; i++) { // print(nums[i]); //} // // Related Topics 数组 双指针
这题没什么好说的,要注意审题,返回数组长度,但同时要对输入的数组进行更改,不能对其进行复制,产生一个新的数组。
public int removeDuplicates(int[] nums) {
int k = 0;
for (int i = 0; i < nums.length; i++) {
int temp = nums[k];
if(nums[i] != temp){
int j = i;
k++;
nums[k] = nums[j];
}
}
return k+1;
}