Leetcode Task05:完成23、26、33题目并打卡
023 合并 K 个有序链表
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
举例
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
解题思路
借助分治的思想,把 K 个有序链表两两合并即可。相当于是第 21 题的加强版。
//leetcode submit region begin(Prohibit modification and deletion)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0)
return null;
return merge(lists, 0, lists.length - 1);
}
private ListNode merge(ListNode[] lists, int left, int right) {
if (left == right)
return lists[left];
int mid = left + (right - left) / 2;
ListNode l1 = merge(lists, left, mid);
ListNode l2 = merge(lists, mid + 1, right);
return mergeTwoLists(l1, l2);
}
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null)
return l2;
if (l2 == null)
return l1;
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1,l2.next);
return l2;
}
}
}
//leetcode submit region end(Prohibit modification and deletion)
026 删除排列数组的重复数项
Given a sorted array nums, remove the duplicates in-place such that each element appear only
once and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array inplace
with O(1) extra memory.
给定⼀个有序数组 nums,对数组中的元素进⾏去重,使得原数组中的每个元素只有⼀个。
最后返回去重以后数组的⻓度值。
举例
Given nums = [1,1,2],
Your function should return length = 2, with the first two elements of nums
being 1 and 2 respectively.
It doesn't matter what you leave beyond the returned length.
解题思路
这道题和第 27 题很像。这道题和第 283 题,第 27 题基本⼀致,这⼀题是删除重复元素,实质是⼀样的。
这⾥数组的删除并不是真的删除,只是将删除的元素移动到数组后⾯的空间内,然后返回数组实际剩余的元素个数,OJ 最终判断题⽬的时候会读取数组剩余个数的元素进⾏输出。
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public int removeDuplicates(int[] nums) {
if(nums == null || nums.length == 0)
return 0;
int p = 0;
int q = 1;
while(q < nums.length){
if(nums[p] != nums[q]){
if(q - p > 1){
nums[p + 1] = nums[q];
}
p++;
}
q++;
}
return p + 1;
}
}
//leetcode submit region end(Prohibit modification and deletion)
复杂度分析
时间复杂度:O(n)。
空间复杂度:O(1)。
033 搜索旋转排序数组
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2] ).
You are given a target value to search. If found in the array return its index, otherwise return -1 .
You may assume no duplicate exists in the array.
Your algorithm's runtime complexity must be in the order of O(log n).
假设按照升序排序的数组在预先未知的某个点上进⾏了旋转。( 例如,数组 [0,1,2,4,5,6,7] 可能变为[4,5,6,7,0,1,2] )。搜索⼀个给定的⽬标值,如果数组中存在这个⽬标值,则返回它的索引,否则返回 -1。你可以假设数组中不存在重复的元素。你的算法时间复杂度必须是 O(log n) 级别。
举例
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
解题思路
- 给出⼀个数组,数组中本来是从⼩到⼤排列的,并且数组中没有重复数字。但是现在把后⾯随机⼀段有序的放到数组前⾯,这样形成了前后两端有序的⼦序列。在这样的⼀个数组⾥⾯查找⼀个数,设计⼀个 O(log n) 的算法。如果找到就输出数组的⼩标,如果没有找到,就输出 -1 。
- 由于数组基本有序,虽然中间有⼀个“断开点”,还是可以使⽤⼆分搜索的算法来实现。现在数组前⾯⼀段是数值⽐较⼤的数,后⾯⼀段是数值偏⼩的数。如果 mid 落在了前⼀段数值⽐较⼤的区间内了,那么⼀定有 nums[mid] > nums[low] ,如果是落在后⾯⼀段数值⽐较⼩的区间内,nums[mid] ≤ nums[low] 。如果 mid 落在了后⼀段数值⽐较⼩的区间内了,那么⼀定有nums[mid] < nums[high] ,如果是落在前⾯⼀段数值⽐较⼤的区间内, nums[mid] ≤ nums[high] 。还有 nums[low] == nums[mid] 和 nums[high] == nums[mid] 的情况,单独处理即可。最后找到则输出 mid,没有找到则输出 -1 。
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public int search(int[] nums, int target) {
if(nums == null | nums.length == 0)
return -1;
int a0 = nums[0];
int low = 0;
int high = nums.length - 1;
if(a0 == target)
return 0;
while(low < high) {
int mid = (low + high) / 2;
if(target == nums[mid])
return mid;
if ((a0 < target && target < nums[mid])
|| (target < nums[mid] && nums[mid] < a0)
|| (nums[mid] < a0 && a0 < target)) {
high = mid;
} else {
low = mid + 1;
}
}
return low == high && target == nums[low] ? low : -1;
}
}
//leetcode submit region end(Prohibit modification and deletion)

浙公网安备 33010602011771号