【LeetCode】【C++】1~3

記錄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;
}
//如果考慮負數,則將加法那一套搬進去,將負數變爲"正的負數即可"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章