记录LeetCode的刷题之旅,目标提高编程技巧,如有疏漏望不吝赐教。Xue 2018.5.7
直接在leetcode官网记录刷题了,就不多此一举了,
目录:
文章目录
1. two sum两数之和
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
C++
vector<int> twoSum(vector<int>& nums, int target)
{
vector<int> vInt;
map<int,int> hash;
for(int idx=0;idx < nums.size();idx++)
{
if(hash.find(target - nums[idx]) != hash.end())
{
vInt.push_back(idx);
vInt.push_back(hash[target-nums[idx]]);
return vInt;
}
else
hash[nums[idx]] = idx;
}
return vInt;
}
2.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.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
题意:有两个非空的链表,其非负整数按照倒序排列(789的倒序排列987)。两个链表中的数进行求和,并以另一个链表表示。
//进位
int nCarry =0;
//retNode链表开始指针,curNode当前节点指针
ListNode *retNode=new ListNode(-1);
ListNode *curNode=retNode;
while(l1 != NULL || l2 != NULL || nCarry)
{
int nSum =0;
if(l1 != NULL)
{
nSum += l1->val;
l1 = l1->next;
}
if(l2 != NULL)
{
nSum += l2->val;
l2 =l2->next;
}
nSum += nCarry;
nCarry = nSum/10;
curNode->val = nSum % 10;
//递推到下一个节点,并申请内存
if(l1 != NULL || l2 != NULL || nCarry)
curNode = (curNode->next =new ListNode(0));
}
return retNode;
遇到的错误:
1,下一个节点没有申请内存,导致崩溃。
2,next指向没有实例化的对象。
大神CODE赏析:
int hasOne = 0;
//链表起始节点为-1,从起点的下一个节点处返回
ListNode preheader(-1);
//cur获取当前节点
ListNode* cur = &preheader;
//两数和在当前位有数的条件
while (l1 || l2 || hasOne) {
//求出综合
int cur_value = (l1?l1->val:0) + (l2?l2->val:0) + hasOne;
//递推下一个节点
l1 = l1?l1->next:NULL;
l2 = l2?l2->next:NULL;
hasOne = cur_value/10;
//当前的下一个节点为当前的计算位
cur->next = new ListNode(cur_value%10);
//将节点下移一个节点位
cur = cur->next;
}
return preheader.next;
3.Longest Substring Without Repeating Characters无重复字符的最长子串
Given a string, find the length of the longest substring without repeating characters.
int lengthOfLongestSubstring(string s)
{
int nSum=0;
string str;
for(int idx=0;idx<s.size();idx++)
{
int nIdx = str.find(s[idx]);
if(nIdx == -1)
str +=s[idx];
else
{
if(str.size() >nSum)
nSum = str.size();
str.erase(0,nIdx+1);
str+=s[idx];
}
}
if(str.size() >nSum)
return str.size();
return nSum;
}
遇到的错误:
1,Map中的存储是以Key的大小排序存储的,错误的认为是像vector一样的尾部追加。
2,固执的再次采用Map,最终耗时过大而弃。(根据value判断其相对位置)
大神CODE:
分析思路
1,重复的判断利用字符ASCII码作为数组索引判断之前是否存在。
2,idx记录每一个重复字符的前一个位置,即记录了下一段非重复字符的起始位置。
int lengthOfLongestSubstring(string s)
{
int locs[256];
//以字符本身的ASCII码为索引,对应的值为对应字符串中的位置
memset(locs, -1, sizeof(locs));
int idx = -1, max = 0;
for (int i = 0; i < s.size(); i++)
{
//判断字符是否存出现在字符串位置idx之后,如果存在将这个位置标记为idx。这样做的目的即可以一直刷新连续非重复的字符。
if (locs[s[i]] > idx)
idx = locs[s[i]];
//求出各分段之间的最大连续个数
if (i - idx > max)
max = i - idx;
//标记字符在字符串中出现的位置
locs[s[i]] = i;
}
return max;
}
[位逻辑]不使用运算符实现Add
Add
int Add(int a,int b){
if(b==0) return a;
int sum = a^b; //不考虑进位情况下的,加法可通过异或实现。
int carry =(a&b)<<1; //进位,左移动。当等于0时则,则值为两数相加的值。
return Add(sum,carry);
}
Sub
int Sub(int a,int b)//相减,即为a+(-b)
{
int reverseb = Add(~b,1);
return Add(a,reverseb);
}
Multi
//a * b 的结果可以写成 a * 20 * b0 + a * 21 * b1 + … + a * 2i * bi + … + a * 231 * b31,其中,bi 为 0 或 1 代表整数 b 的二进制表达中第 i 位的值。
int Multi(int a, int b) {
int res = 0;
while(b != 0){
if((b & 1) != 0)
res = Add(res, a);
a <<= 1;//左移
b >>= 1;//右移
}
return res;
}
//如果考虑负数,则将加法那一套搬进去,将负数变为"正的负数即可"