LeetCode Week1: Two Sum、Add Two Numbers、Median of Two Sorted Arrays
来源:互联网 发布:选择linux内核启动 编辑:程序博客网 时间:2024/05/16 14:51
这一周实现了LeetCode Algorithms中的1、2、4题,分别是Two Sum(easy)、Add Two Numbers(medium)、Median of Two Sorted Arrays(Hard)。
一、Two Sum
题目描述:Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution, and you may not use the same element twice.
Examples:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
分析:题目是要找到和为目标值的两个数的位置,因为保证了答案只会有一组,难度已经减了很多。直接循环判断哪一个数的值等于目标值减去当前值即可得到两个数的位置,这个是最基础的方法,算法相对也比较简单,两重循环即可解决,算法的复杂度是
for(vector<int>::iterator it = nums.begin() ;it!=nums.end();it++){ diff = target - *it; j = i+1; for(vector<int>::iterator it1 = it+1 ;it1!=nums.end();it1++){ if(diff == *it1){ result.insert(result.begin(),i); result.insert(result.begin()+1,j); return result; } j +=1; } i += 1;}
通过Submission一看,这种方法跑的Run Time要238ms,实在是太慢了==,所以又有了想要提升的想法。
考虑到了原本参数传递中就有了容器,很多容器都可以直接做查询,而且每次比对vector中的数值时同时还需要考虑其对应位置,这样的情况下用map会比较好,我使用了unordered_map, map以及hash_map,hash_map在没有冲突的情况下运算量是
vector<int> twoSum(vector<int>& nums, int target) { map<int,int>hash; vector<int> result; int diff = 0; for(int i = 0;i < nums.size();i++){ diff = target - nums[i]; // 寻找已经计算过的数值中有没有与差值相等的 if(hash.find(diff) != hash.end()){ result.push_back(hash[diff]); result.push_back(i); return result; } // 没有与差值相等的数值,将当前位置值及位置放入hash中备用 hash[nums[i]] = i; }}
hash变量的类型可以改为unordered_map,相应的头文件也从#include
通过查阅其他博客,可以了解到unordered_map运行效率比map高,但占用内存也比map大,估计是因为LeetCode的测试用例都比较小,所以运行时看不出太大区别。
二、Add Two Numbers
题目描述:You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Examples:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
分析:其实这个题考查的主要是对链表的操作,无奈自己本科学的忘得最多的就是链表了,所以这个题目的难点主要就是对链表的基本操作了。
注意几个临界条件:
1. l1与l2的长度不一致,需要计算下一位时l1->next或者l2->next会为空,那么就会出错。利用三元操作符进行判断,如果链表已经为空0,那么不指向next,计算的值也默认为0;
v1 = ((l1 != NULL)?l1->val:0); v2 = ((l2 != NULL)?l2->val:0); …… l1 = ((l1 != NULL)?l1->next:NULL); l2 = ((l2 != NULL)?l2->next:NULL);
- 之前没有考虑好最后一位计算时的进位问题,导致对于Input:(5)+(5)的问题出错,得到的结果为0,其实应该是[0,1],这也说明只有进位为0,l1和l2都为空,计算才应该停止。
具体代码如下:
class Solution {public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { int v1 = 0, v2 = 0; int sum = 0, in = 0; ListNode* result = new ListNode(0); // head指向result的头指针位置 ListNode* head = result; while(l1!=NULL || l2!= NULL || in != 0){ // 保证每次都有值运算 v1 = ((l1 != NULL)?l1->val:0); v2 = ((l2 != NULL)?l2->val:0); sum = v1+v2+in; in = sum/10; head->next = new ListNode(sum%10); head = head->next; l1 = ((l1 != NULL)?l1->next:NULL); l2 = ((l2 != NULL)?l2->next:NULL); } return result->next; }};
反思:之前一直认为head=result是指head的值与result的值相等,但是对于链表,这是表示head执行了result的头指针的地址,我们对head进行操作,也会相应的改变result的值,不断的修改head=head->next,使得head指向一下结点的位置,而不是用result=result->next的操作。
三、Median of Two Sorted Arrays
题目描述:There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be
Example1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
分析:这个题如果没有算法复杂度要
因为复杂度是带
最后决定使用的是寻找第
如果k是奇数,比如11,那么将两个数组合起来的第
- 我们先做调整,使得A为长度较小的序列,B为长度较大的序列;
- 选取A中的第
k2 个元素(如果A的长度小于12 ,那么就直接选取A的第m 个元素,这里假设先假设是k2个元素),选取B的第 (k-\frac{k}{2})$个元素; - 比较
ak2 和bk2 :ak2 =bk2 ,那么第k 个元素就是这两个元素中随意一个;ak2 >bk2 ,那么b1 …bk2−1 的元素肯定在前k个元素中,肯定比第k 个元素小,可以把它们去除掉,减少选择的数目。这样需要判断的个数就剩下(k−k/2) 个了;ak2 <bk2 ,操作同上,去除a1 到ak2−1 的元素。
- 重复上述操作,当到达下述边界条件时,即可得到第
k 个元素- 如果短序列A已经空了,那么第
k 个元素一定不在A中,而是序列B中的bk−1 ; - 如果已经去除了
k−1 个元素两个序列都还未空,那么两个序列中较小的零元素就是第k 个元素。
- 如果短序列A已经空了,那么第
需要注意的是,如果总的序列的长度为偶数,那么需要找到的中位数为两位,那么还需要找到第
鉴于每一次都是调用前一次的方法,递归方法可以用来实现本次实验,因为上述的讨论中都是直接考虑了第几个数,但是序列的计数是从0开始的,所以在编码的时候需要-1。
程序的相关代码如下:
class Solution {public: double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int s1 = nums1.size(), s2 = nums2.size(); if ((s1 +s2)%2==0){ // 如果序列总长度为偶数,找到两个数,其均值为中位数 vector<int>n1,n2; n1 = nums1,n2 = nums2; return (findkth(nums1,nums2,(s1+s2)/2+1)+findkth(n1,n2,(s1+s2)/2))/2; } else return findkth(nums1,nums2,(s1+s2)/2+1); } double findkth(vector<int>& nums1, vector<int>& nums2,int k){ // 保证前一个序列一直是短序列 if(nums1.size() > nums2.size()) return findkth(nums2,nums1,k); // 第k个数不在nums1中 if(nums1.size()==0) return nums2[k-1]; // 两个序列中比第k个数小的数都已经去除 // 两个序列中较小的首元素就是第k个数 if(k == 1) return ((nums2[0]>nums1[0])?nums1[0]:nums2[0]); int k_2,len1,ns1,ns2; len1 = nums1.size(); k_2 = k/2, ns1 = ((k_2>len1)?len1:k_2), ns2 = k - ns1; if(nums1[ns1-1] < nums2[ns2-1]){ // 去除前k个数中的ns1个数,减少对比工作量 nums1.erase(nums1.begin(),nums1.begin()+ns1; k -= ns1; } else if(nums1[ns1-1] > nums2[ns2-1]){ nums2.erase(nums2.begin()+0,nums2.begin()+ns2); k -= ns2; } else return nums1[ns1-1]; return findkth(nums1,nums2,k); }};
反思:这次的实验理清了思路之后其实就能很快实现了,但是粗心的我还是会在判别最终的临界条件时出错。最后答案一直出错的问题是在传参上,因为引用传参直接就修改了两个vector的值,对于总序列长度为偶数需要两次调用findkth()函数时第二次调用的函数会直接使用上一次已经被去除了一部分元素的nums1和nums2,造成了计算结果的错误。后来我比较偷懒的多声明了两个变量n1和n2,来解决这个问题,其实还可以直接传vector的起始位置来避免使用erase,因为时间关系这里就不多做叙述了。
感觉太久没刷题了生疏了好多== 但是刷题的感觉很爽啊,虽然中途卡了好久。立个小小的flag,以后要每天刷一题^^
- LeetCode Week1: Two Sum、Add Two Numbers、Median of Two Sorted Arrays
- LeetCode: Median of Two Sorted Arrays
- LeetCode Median of Two Sorted Arrays
- leetcode 26: Median of Two Sorted Arrays
- Leetcode 4 Median of Two Sorted Arrays
- [Leetcode] Median of Two Sorted Arrays
- LeetCode 4 - Median of Two Sorted Arrays
- [LeetCode]Median of Two Sorted Arrays
- leetcode Median of Two Sorted Arrays
- LeetCode-Median of Two Sorted Arrays
- [LeetCode] Median of Two Sorted Arrays
- [LeetCode] Median of Two Sorted Arrays
- [leetcode] Median of Two Sorted Arrays
- leetcode-004:Median of Two Sorted Arrays
- Leetcode 4 Median of Two Sorted Arrays
- leetcode之 median of two sorted arrays
- 【转载】【leetcode】Median of Two Sorted Arrays
- LeetCode - Median of Two Sorted Arrays
- 【Linux】linux常用基本命令
- 最小数和最大数
- OpenLayer3 之 实现拉框放大功能
- Vue中router-link介绍
- java报错排解
- LeetCode Week1: Two Sum、Add Two Numbers、Median of Two Sorted Arrays
- C++命名空间
- BZOJ 4553 HEOI 2016 seq
- 3.环境搭建-Hadoop(CDH)集群搭建
- Unity-String格式化字符串
- beggo介绍
- myeclipse破解器一闪而过的原因
- poj3258
- sysfs文件系统