【LeetCode】【C++】1~3

记录LeetCode的刷题之旅,目标提高编程技巧,如有疏漏望不吝赐教。Xue 2018.5.7
直接在leetcode官网记录刷题了,就不多此一举了,

目录:

文章目录

  • 1. two sum两数之和
  • 2.add two numbers两数相加
  • 3.Longest Substring Without Repeating Characters无重复字符的最长子串
  • [位逻辑]不使用运算符实现Add

1. two sum两数之和

 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
C++

vector twoSum(vector& nums, int target) 
 {
      vector vInt;
        
	  map 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;idxnSum)
				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;
}
//如果考虑负数,则将加法那一套搬进去,将负数变为"正的负数即可"

你可能感兴趣的:(LeetCod)