0
点赞
收藏
分享

微信扫一扫

指针练习

167.两数之和 II - 输入有序数组

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列,请你从数组中找出满足相加之和等于目标数 target 的两个数。

如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。 以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。 你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。你所设计的解决方案必须只使用常量级的额外空间。

示例 1:

输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
示例 2:

输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
示例 3:

输入:numbers = [-1,0], target = -1
输出:[1,2]
解释:-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
思路:

第一次编写当然想到最简单的是循环累加,成功就return。结果运行下面代码会超时,两层循环效率当然慢的没边。

std::vector<int> twoSum(std::vector<int>& numbers, int target) {
int idx = 0, idx1 = 0;
const int lens = numbers.size();
for (idx = 0; idx < lens; ++idx)
{
for (idx1 = idx + 1; idx1 < lens; ++idx1)
{
if (numbers[idx] + numbers[idx1] == target)
return { idx + 1,idx1 + 1 };
}
}
return { 0,0 };
}
优化思路:

保持一层循环,首先首尾各一个指针,因为是有序的:下标start_ptr + end_ptr 取值 > 目标 ,j就要缩小范围,反之i就要增加.

vector<int> twoSum(vector<int>& numbers, int target) {
int start_ptr = 0, end_ptr = numbers.size() - 1;
while (start_ptr < end_ptr) {
if (numbers[start_ptr] + numbers[end_ptr] > target)
--end_ptr;
else if (numbers[start_ptr] + numbers[end_ptr] < target)
++start_ptr;
else
return { start_ptr + 1, end_ptr + 1 };
}
return { start_ptr, end_ptr };
}

还有用二分法优化的,o(n) --> o(1)这里不做优化了,后面有二分法的专项 LeetCode See: https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted/

88. 合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。 示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
示例 2:

输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。
示例 3:

输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
思路:

首先要以nums1长度为准,不然以防拷贝越界,也不会有问题毕竟输入的时候有检测leetcode示例 nums1[m]下标开始复制,比如Nums2里面10个元素,倒序复制最后排序即可

void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
const int nums1_len = nums1.size();
do {
for (int i = m; i < nums1_len; ++i)
{
nums1[i] = nums2[--n];
if (n == 0) break;
}
} while (false);
std::sort(nums1.begin(), nums1.end());
}

LeetCode See: https://leetcode.cn/problems/merge-sorted-array/

142. 环形链表 II

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。

为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。 不允许修改 链表。

没读懂题目意思......

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

官方答案,我这替补做任何描述了,因为即使看了答案我也没明白他到底想要考察什么?首先真实场景中一定是遍历元素val返回我们需要的对象,进行增删改查.

unordered_set<ListNode *> visited;
while (head != nullptr) {
if (visited.count(head)) {
return head;
}
visited.insert(head);
head = head->next;
}
return nullptr;

LeetCode See: https://leetcode.cn/problems/linked-list-cycle-ii/

举报

相关推荐

0 条评论