代码随想录算法训练营Day6|242有效字母异位、349求两个数组的交集、

1.3leetcode242有效字母异位

这题在开营前琢磨过,复习了一下,leetcode上记了笔记,就直接抄过来了

第一次解答忘记了在判断长度是否相等后,长度不相等可以直接返回false,不需要往下判断了。

没通过的原因,有部分是因为不熟悉C++的使用,一些功能不知道怎么调用。

最简单的办法是暴力破解,用双重循环遍历,同时记录下相同字母的字母数量,时间复杂度是O(n^2).

看了其他人的题解得到的收获:

收获1(用排序去解)

先排序再判断长度,长度不等就false.

收获2(定义数组的方法)

定义数组的方法可以是,将字符串以每个字符分别放进数组

char[]str1 = s.toCharArray();
char[]str2 = t.toCharArray();

其中的s是一个已知的字符串。

数组排序可以是直接用Array.sort函数对数组str1和数组str2进行排序

Array.sort(str1);
Array.sort(str2);

[用哈希表求解思路]

哈希表的本质是数组,我们就定义一个大小为26的数组,对应值初始化为0,用来记录每个小写字母出现的次数,先遍历s当该字母出现一次就+1,再遍历,出现一次就-1,最后判断是否都为0,如果是,那么s和t就是彼此的异位字母。

[收获4]

使用数组元素对字母进行计数时,考虑用当前字母的ASCII码减去‘a’,也就是减去96,这样可以得到26个小写字母从0--25的索引所对应的位置,可以节省空间。

int record[26]={0};
for(int i=0;i

[收获5]

判断两个字符串是否相等可以使用函数Array.equals

返回值是bool型,可能是false或true.

Arrays.equals(str1,str2);

完整求解代码:

class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.length()!=t.length()){return false;}
    int record[26]={0};
    for(int i=0;i

2.两个数组的交集

set

使用数组做哈希表是因为题目限制了数值的大小,当不再限制数值的大小时,就无法使用数组来做哈希表。如果哈希值比较小、特别分散、跨度很大,就会造成数组空间浪费。这时选择set.

set在C++中有3种可用的数据结构,std::set  ;   std::multiset  ;   std::unordered_set  ;

std::set和std::multiset底层实现是红黑树,std::unordered_set的底层实现是哈希表。

[题目思路]

这题使用std::unordered_set,它读写效率最高,无需排序,数据不重复。

这题不涉及太复杂的算法,只要用一个循环遍历,找出同时出现在num1和num2中的数即可。用set是为了使数据不重复。

将一个普通数组转化成unordered_set 形式,使用nums_set(Arrays.begin(),Arrays.end());

unordered_setnums_set(nums1.begin(),nums1.end());//将数组nums1变成unordered_set类型

求解的源代码:

class Solution {
public:
    vector intersection(vector& nums1, vector& nums2) {
     unordered_set result_set;
     unordered_setnums_set(nums1.begin(),nums1.end());
     for(int num:nums2)
     {
         if(nums_set.find(num) !=nums_set.end()){
             result_set.insert(num);
         }
     }
     return vector(result_set.begin(),result_set.end());
    }
};

set的直接使用不仅空间比数组大,而且速度比数组慢,set把数值映射到key上都要做hash计算的。在数量大的情况下,差异会很显著。

3.202快乐数

原题链接leetcode202快乐数

[哈希法求解]

题目要求将正整数的每位的数字平方求和,有和为1就true,无则继续找,至sum重复出现,false.

可以写一个函数对数值各个位上的单数之和进行求解

int getSum(int n){
  int sum = 0;
  while(n){
    sum += (n % 10)*(n % 10);//对一个整数取余,得到的是个位数
    n/=10;
    }
  return sum;
 }

使用set求解,设置一个unordered_set的容器set,只要判断出当前的sum不在set里,就将这个sum通过insert()函数添加到set,每得到一个sum,就执行一次判断,直到出现和set容器内存放的值相等的sum,就返回false.结束循环,这种方式来判断sum是否重复出现。

unordered_setset;
while(1){
int sum = getsum(n);//调用getsum()求sum的函数
   if(sum == 1){
     return true;
     }
  if(set.find(sum) != set.end()){
  return false; //重复了,直接返回false
  }else{
    set.insert(sum);//将没有重复的sum插入进set
  }
 n = sum;
}

完整求解代码如下:

class Solution {
public:
    int getsum(int n){
        int sum = 0;
        while(n)
        {
            sum += (n % 10) * (n % 10);
            n /= 10;
        }
        return sum;
    }
    bool isHappy(int n) {
    unordered_setset;
    while(1){
        int sum = getsum(n);
        if(sum == 1){
            return true;
        }
        if(set.find(sum) != set.end()){
            return false;
        }else{
            set.insert(sum);
        }
        n=sum;
    }
    }
};

两数之和

原题链接:1.两数之和

[关于map]map分三种,std::map和std::mutimap底层是红黑树,std::unoredered_map底层是哈希表。

map有两个值value和key,value是数组元素下标,key是数组元素。

遍历数组时,向map去查询是否有与当前被遍历到的元素相同的数值,有,就找到对应的key和value,没有就把这个被遍历到的元素放进map,这里和前一个题目unordered_set的set思路一样。

在定义mao时记得map中是key和value两个值,所以应用

std::unordered_mapmap;

对数组遍历,找和map中某个元素相同的元素,如果有就返回value和key,如果没有,就把它的value,key通过insert()函数记录进map。

map.insert(pair(nums[i],i));

完整求解代码如下:

class Solution {
public:
    vector twoSum(vector& nums, int target) {
        std::unordered_mapmap;
        for(int i = 0;i < nums.size();i++)
        {
            auto iter = map.find(target - nums[i]);
            if(iter != map.end()){
                return{iter->second,i};
            }
            map.insert(pair(nums[i],i));
        }
        return{};
    }
};

你可能感兴趣的:(算法)