只出现一次的数字、不用加减乘除做加法、同构字符串

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

解法1:位异或:
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret = 0;
        for (auto e: nums) ret ^= e;//这里运算符的逻辑没太懂
        return ret;
    }
};

解法2 :用容器定义的哈希表来做。
空间复杂度O(n)

class Solution {
public:
    int singleNumber(vector<int>& nums) {
     vector<int>tmpnums(10,0);
		for (int val : nums)
		{
			tmpnums.at(val) += 1;
		}
		for (int i=0;i<10;i++)
		{
			if (tmpnums.at(i) == 1)
			{
				return i;
			}
		}
		exit(0);
	}
};

这里有个问题就是第一,如果不初始化自定义的容器tmpnums,那么leecode在测试时会出现越界。在一个基于范围的for不能返回下标,所以我们只能用普通的for来返回哈希的下标。但是还有一个更重要的问题,容器的下标都是从零开始,测试用例给个负数就没法办了。所以这个代码还是非常受局限的。编译器给的哈希表我也不会用。。。。。。。

剑指offer:不用加减乘除做加法

在这里插入图片描述

class Solution {
public:
    int add(int a, int b) 
    {
        int carry;
        while(b)
        {
         carry=a&b;//进位
         a=a^b;//先求本位
        b=(unsigned)carry<<1;
        }
        return a;
    }
    
};

这道题想要做出来必须要知道的是cpu累加器的原理(半累加器:求进位用(&)加异或(^),求本位用异或)).

用循环来模拟全累加器。每一个循环都是单个位的累加计算。
例子(15和8)
第一次:(1111的最后一位)1 0(1000的最后一位) 的位累加 :
进位 0(1&0得0 再进位还是0;就不进位了)
本位1 (1^0得1) --> 所以本位(结果的最后一位填1)
第二次(同理) 1 和0
进位 为0
本位为1
第三次 1 和0
进位 为0
本位为1
第四次 1和1
进位为1 (本位求完后再进位 )
本位为0 所以结果的正数第二位,也就是15+8的23(10111)的左数第二位。

进位的1与0(此位没数自动设为0)异或得1 所以 左数第一位是1.
最后的结果为(1111+1000)=(10111)=23

同构字符串

给定两个字符串 s 和 t ,判断它们是否是同构的。

如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。

每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。

数学上的映射关系:

在这里插入图片描述

class Solution {
public:
    bool isIsomorphic(string s, string t) {
        unordered_map<char,char>s2t,t2s;//定义两个哈希表

        for(int i=0;i<s.size();i++)
        {
            char a=s[i],b=t[i];   //把键值对的两个值分别存起来 方便coding
            if((s2t.find(a)!=s2t.end()&&b!=s2t[a])||(t2s.find(b)!=t2s.end()&&a!=t2s[b]))
            // if 语句||前面,&&前半段是判断是否找到了这个这个值,如果已经找到这个值,说明有这个映射的键值对,&&后半段是判断已经有的键值对映射在哈希表里的值与新循环的i对应 的即将放入哈希表中的b比较,不相同则说明不是一一对应的映射关系,则返回false;
        //    因为映射是双向的,所以也得判断相反方向是否出现一不对一的情况。
        {
                return false;
        }
     
        s2t[a]=b;//把a映射的b存在2s2t中
         t2s[b]=a;
        }
        return true;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值