記錄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;
}
//如果考慮負數,則將加法那一套搬進去,將負數變爲"正的負數即可"