360内推笔试编程题2017

360笔试编程题一共三道:360春招&实习生招聘3.25在线编程题解

第一题是给出根据数学期望的公式编程实现,需要注意的是结果要求四舍五入保留三位小数,详情见链接。

第二题是求给定的字符串的子串中偶串的个数,偶串是指字符串中每个字母出现的次数均为偶数。

一种思路:

遍历所有子串,判断每个子串是否为偶串,判断方法为:建一个map,遍历子串的每个字符,遍历到某个字符时,判断map中是否包含该字符,如果不包含就以该字符为key将它put进去,如果包含就将它移除。某次循环结束时,如果map为空,则表示这个子串为偶串。

/*
代码如下
*/

public int evenSubStringNum(String s) {
        if (s == null) {
            return 0;
        }

        Map<Character, Character> map = new HashMap<>();
        char[] charArr = s.toCharArray();
        int sum = 0;
        for (int i = 0; i < charArr.length; i++) {
            for (int j = i; j < charArr.length; j++) {
                if (!map.containsKey(charArr[j])) {
                    map.put(charArr[j], charArr[j]);
                } else {
                    map.remove(charArr[j]);
                }
                if (map.isEmpty()) {
                    sum++;
                }
            }
            map.clear();
        }
        return sum;
    }

上述解法时间复杂度较高,笔试结束后在赛码网上看到了更优的解法,利用异或运算符求解,C++代码如下:

#include <bits/stdc++.h>
#define maxn 100009
using namespace std;
char s[maxn];
map<int,int>mp;
int n;
int main(){
    scanf("%s",s);
    n = strlen(s);
    mp[0] = 1;
    int cur = 0;
    long long ans = 0;
    for(int i = 0; i < n; i++){
        int x = s[i] - 'a';
        cur ^= (1 << x);
        ans += mp[cur];
        mp[cur]++;
    }
    cout << ans << endl;
    return 0;
}

自己转换成Java代码如下:

    public int evenSubStrings(String s) {
        Map<Integer, Integer> map = new HashMap<>();
        char[] chars = s.toCharArray();
        int n = chars.length;
        int cur = 0;
        int ans = 0;
        map.put(0, 1);
        for (int i = 0; i < n; i++) {
            int x = chars[i] - 'a';
            cur ^= (1 << x);
            ans += map.get(cur) == null ? 0 : map.get(cur);
            if (map.get(cur) == null) {
                map.put(cur, 1);
            } else {
                map.put(cur, map.get(cur)+1);
            }
        }
        return ans;
    }

没有看懂,在评论里见到了一个解释,摘抄如下:

我来解释一下第二题好了,,,扫一遍记录下每个前缀子串的状态(每个字母出现的次数为奇/偶)。如果两个前缀状态相同,说明夹在它们中间的子串肯定是个偶串。我是组合数算的,相同状态的前缀两两组合都是一个偶串,像题解里每次相加也行。

因为只有26个字母,所以可以状态压缩,用 32 位 int 的其中 26 位来记录状态,某位为 0 表示 该位对应的字母为偶数。

1<<26的状态数太大了所以用map存。注意有个坑是mp[0] = 1,不然20%会挂掉。

posted @ 2017-03-26 22:11  细雨落花  阅读(789)  评论(0编辑  收藏  举报