463. Island Perimeter\242. Valid Anagram\*260. Single Number III\409. Longest Palindrome

463. Island Perimeter

题目描述

You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represents water. Grid cells are connected horizontally/vertically (not diagonally). The grid is completely surrounded by water, and there is exactly one island (i.e., one or more connected land cells). The island doesn’t have “lakes” (water inside that isn’t connected to the water around the island). One cell is a square with side length 1. The grid is rectangular, width and height don’t exceed 100. Determine the perimeter of the island.

Example:

[[0,1,0,0],
 [1,1,1,0],
 [0,1,0,0],
 [1,1,0,0]]

Answer: 16
Explanation: The perimeter is the 16 yellow stripes in the image below:

这里写图片描述

这道题目就是求由1围成的图形中,它的周长是多少。而且这道题目只有一个由1围成的图形,非常简单。

这里使用BFS足以搞定它,使用BFS的话,对付多个也能应付自如。而且在图形内部没有由0组成的形状,又降低了一个难度。

代码实现

碰到一个1以后把它压入队列中,然后遍历四周,四个方向,根据这个计算周长数目。

class Solution {
public:
    int islandPerimeter(vector<vector<int>>& grid) {
        int m = grid.size(), n = m?grid[0].size():0, perimeter = 0;
        if(!m) return perimeter;
        queue<pair<int, int>> pos;
        int shift[] = {-1, 0, 1, 0, 0, 1, 0, -1};
        for(int row = 0; row < m; row++) {
            for(int col = 0; col < n; col++) {
                if(grid[row][col] == 1) {
                    pos.push(make_pair(row, col));
                    while(!pos.empty()) {
                        int y = pos.front().first, x = pos.front().second;
                        pos.pop();
                        perimeter += 4;
                        for(int neigh = 0; neigh < 4; neigh++) {
                            if(y+shift[neigh] >= 0 && y+shift[neigh] < m && x+shift[neigh+4] >= 0 && x+shift[neigh+4] < n && grid[y+shift[neigh]][x+shift[neigh+4]]) {
                                if(grid[y+shift[neigh]][x+shift[neigh+4]] == 1)  { pos.push(make_pair(y+shift[neigh], x+shift[neigh+4]));
                                    grid[y+shift[neigh]][x+shift[neigh+4]] = 2;

                                }
                                perimeter--;
                            }    
                        }        
                        grid[y][x] = 2;
                    }
                    return perimeter;
                }
            }
        }
        return perimeter;
    }
};

242. Valid Anagram

题目描述

Given two strings s and t, write a function to determine if t is an anagram of s.

For example,
s = “anagram”, t = “nagaram”, return true.
s = “rat”, t = “car”, return false.

Note:
You may assume the string contains only lowercase alphabets.

Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?

这道题目就是求在两个字符串是否由相同个数的小写字母组成。

这里我使用的是简单的一个vector的数组来存其出现的次数,一个字符串做加,另外一个做减。所以可以看出最后判断数组是否全为0就可以判断结果了。

当然如果是unicode编码的字符串的话,那么数据结构我会改成更大的数组或者使用map。

代码实现

class Solution {
public:
    bool isAnagram(string s, string t) {
        vector<int> hash(26, 0);
        int slen = s.length(), tlen = t.length();
        if(slen != tlen) return false;
        for(int i = 0; i < slen; i++) {
            hash[s[i]-'a']++;   hash[t[i]-'a']--;
        }
        for(auto i:hash) if(i) return false;
        return true;    
    }
};

260. Single Number III

题目描述

Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.

For example:

Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].

Note:

  • The order of the result is not important. So in the above example, [5, 3] is also correct.
  • Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?

    这个就是说一个数组里,有的数字只出现了一次,把这些数字返回。后来发现题目中说这样的数字只有两个。

这个就是用hash了,不能再明显了。

这里我是用的是map,主要是无法提前知道数字的范围,不好设计。这里还有一个问题,就是当返回的向量为空的时候,需要返回[0, 0]

代码实现

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        map<int, int> hash;
        vector<int> res;
        int len = nums.size();
        for(int i = 0; i < len; i++) {
            hash[nums[i]]++;
        }
        for(map<int, int>:: iterator it = hash.begin(); it != hash.end(); it++) 
            if(it->second == 1)  res.push_back(it->first); 
        if(res.empty()) { res.push_back(0);  res.push_back(0); }    
        return res;
    }
};

当然我的代码好像是没有满足O(1)space的空间要求,所以呢看了一下别人的解法,使用的是bit manipulation.

所以使用这里使用的方法是先找到这两个数字的抑或结果,因为出现两次的通过抑或以及消除了。

for (auto item : nums) aXorb ^= item;

使用下面的公式找到结果的两个数最开始不同的bit位。

(aXorb & (aXorb - 1)) ^ aXorb;

然后根据是否和lastbit可以与作为标准,把数字分成了两个部分。然后一个就是需要的数字a,另外一个就是b。这里的操作比较难懂的就是:

(aXorb & (aXorb - 1)) ^ aXorb;

比如1111和0011,就可以发现lastbit就是0100,是两个数字最开始不同的低位。

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        int aXorb = 0;  // the result of a xor b;
        for (auto item : nums) aXorb ^= item;
        int lastBit = (aXorb & (aXorb - 1)) ^ aXorb;  // the last bit that a diffs b
        int intA = 0, intB = 0;
        for (auto item : nums) {
            // based on the last bit, group the items into groupA(include a) and groupB
            if (item & lastBit) intA = intA ^ item;
            else intB = intB ^ item;
        }
        return vector<int>{intA, intB};
    }    
};

409. Longest Palindrome

题目描述

Given a string which consists of lowercase or uppercase letters, find the length of the longest palindromes that can be built with those letters.

This is case sensitive, for example “Aa” is not considered a palindrome here.

Note:
Assume the length of given string will not exceed 1,010.

代码实现

计算其字符出现的数量,如果是偶数直接加到后面的结果,如果是奇数,那么就要加上奇数减一。然后如果出现奇数项,就要在最后结果加一。

class Solution {
public:
    int longestPalindrome(string s) {
        int len = s.length(), res = 0;
        vector<int> hash(52, 0);
        for(int i = 0; i < len; i++) {
            if(s[i] >= 'a' && s[i] <= 'z')  hash[s[i]-'a']++;
            else hash[s[i]-'A'+26]++;
        }    
        bool isOdd = false;
        for(int i = 0; i < 52; i++) {
            if(hash[i]&1) isOdd = true;
            res += (hash[i] >> 1) << 1;  
        }
        return res + isOdd;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值