文章目录
一、数组中紧跟 key 之后出现最频繁的数字
1、算法:哈希表
对于所有的
key
,把它下一个数哈希计数,然后统计所有哈希出来的最大的那个数。
2、源码
int mostFrequent(int* nums, int numsSize, int key){
int hash[1001];
int i, max;
memset(hash, 0, sizeof(hash));
for(i = 0; i <= numsSize - 2; ++i) {
if(nums[i] == key) {
++hash[ nums[i+1] ];
}
}
hash[0] = -1;
max = 0;
for(i = 1; i <= 1000; ++i) {
if(hash[i] > hash[max]) {
max = i;
}
}
return max;
}
二、将杂乱无章的数字排序
1、算法:多关键字排序
相当于两个关键字的排序,一个是映射后的值,一个是数组下标,模拟处理完,比较函数写好,做一次排序就行了。
2、源码
typedef struct {
int val;
int mapval;
int input;
}Ptr;
int cmp(const void *a, const void *b) {
Ptr *pa = (Ptr *)a;
Ptr *pb = (Ptr *)b;
if(pa->mapval == pb->mapval) {
return pa->input - pb->input;
}
return pa->mapval - pb->mapval;
}
Ptr ptr[30005];
int* sortJumbled(int* mapping, int mappingSize, int* nums, int numsSize, int* returnSize){
int stk[20], top;
int n = numsSize;
int i;
int power;
int *ret = (int *)malloc( sizeof(int) * n );
for(i = 0; i < n; ++i) {
top = 0;
ptr[i].val = nums[i];
ptr[i].mapval = nums[i] ? 0 : mapping[0];
ptr[i].input = i;
power = 1;
while(nums[i]) {
ptr[i].mapval += power * mapping[ nums[i] % 10 ];
nums[i] /= 10;
power *= 10;
}
}
qsort(ptr, n, sizeof(Ptr), cmp);
for(i = 0; i < n; ++i) {
ret[i] = ptr[i].val;
//printf("%d ", ptr[i].mapval);
}
*returnSize = n;
return ret;
}
三、有向无环图中一个节点的所有祖先
1、算法:深度优先搜索
注意到总的边数不会超过 2000,所以
dist[i][j]
表示i
能否到j
,对于每个i
,根据边进行一次深度优先搜索,总的时间复杂度只有 O ( n m ) O(nm) O(nm),然后再遍历dist[i][u]
数组统计每个结点u
能由哪些结点到达即可。
2、源码
class Solution {
void dfs(int start, int u) {
int i;
if(dist[start][u] == 1) {
return ;
}
dist[start][u] = 1;
for(i = 0; i < e[u].size(); ++i) {
dfs(start, e[u][i]);
}
}
public:
vector<vector<int>> getAncestors(int n, vector<vector<int>>& edges) {
vector<vector<int>> ans;
int i, j;
for(i = 0; i < n; ++i) {
e[i].clear();
}
for(i = 0; i < edges.size(); ++i) {
int from = edges[i][0];
int to = edges[i][1];
e[ from ].push_back( to );
}
memset(dist, -1, sizeof(dist));
priority_queue <int> q;
for(i = 0; i < n; ++i) {
dfs(i, i);
}
for(i = 0; i < n; ++i) {
vector<int> ret;
for(j = 0; j < n; ++j) {
if(i != j && dist[j][i] == 1) {
ret.push_back(j);
}
}
ans.push_back(ret);
}
return ans;
}
private:
vector <int> e[1010];
int dist[1010][1010];
};
四、得到回文串的最少操作次数
1、算法:贪心
先确定外层,再确定内层。
1)对于最左边的字符,在右边找一个最接近的,计算步数;
2)对于最右边的字符,在左边找一个最接近的,计算步数;
3)选择 1)和 2) 中的少的步数执行交换,然后再计算内层。
2、源码
int dfs(char *s, int l, int r) {
int i, pos1, pos2, ans;
if(l == r) {
return 0;
}
if(l - 1 == r) {
return 0;
}
for(i = r; i >= l; --i) {
if(s[l] == s[i]) {
pos1 = i;
break;
}
}
for(i = l; i <= r; ++i) {
if(s[i] == s[r]) {
pos2 = i;
break;
}
}
if(pos2 - l < r - pos1) {
for(i = pos2; i > l; --i) {
s[i] = s[i-1];
}
ans = pos2 - l;
}else {
for(i = pos1; i < r; ++i) {
s[i] = s[i+1];
}
ans = r - pos1;
}
return ans + dfs(s, l+1, r-1);
}
int minMovesToMakePalindrome(char * s){
int l = 0;
int r = strlen(s) - 1;
return dfs(s, l, r);
}