刷题日记 - 12
难度:中等
滑动窗口
会员题,CSDN地址:【leetcode】159 至多包含两个不同字符的最长子串(滑动窗口,双指针)_leetcode 159. 至多包含两个不同字符的最长子串 c语言-CSDN博客
在牛课上看到说是华为的面试手撕题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Solution { public static int lengthOfLongestSubstringTwoDistinct(String s) { char[] chars = s.toCharArray(); int len = chars.length;
int left = 0; int right = 0; int[] cnt = new int[26]; int count = 0; int res = 0;
while(right<len){ char rightChar = chars[right++]; if(cnt[rightChar-'a']==0){ count++; } cnt[rightChar-'a']++; while(count>2){ char leftChar = chars[left++]; cnt[leftChar-'a']--; if(cnt[leftChar-'a']==0)count--; } res = Math.max(res,right-left); }
return res; } }
|
普通的滑动窗口,需要用count记录当前窗口中的字符种数,cnt数组维护具体字符的个数。
难度:中等
图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| class Solution { public int shortestBridge(int[][] grid) { int n = grid.length;
int x = -1; int y = -1; for (int i = 0; i < n; i++) { boolean flag = true; for (int j = 0; j < n; j++) { if (grid[i][j] == 1) { x = i; y = j; flag = false; break; } } if (!flag) break; }
int res = -1; for (int i = 1; i <= n; i++) { if (dfs(i, x, y, grid) == true) { res = i - 1; break; } } return res; }
private boolean dfs(int round, int x, int y, int[][] grid) { if (x < 0 || y < 0 || x >= grid.length || y >= grid.length) { return false; } int curVal = grid[x][y]; if (curVal == round) { grid[x][y] = round + 1; boolean a = dfs(round, x - 1, y, grid) || dfs(round, x + 1, y, grid); boolean b = dfs(round, x, y - 1, grid) || dfs(round, x, y + 1, grid); return a || b; } else if (curVal == 0) { grid[x][y] = round + 1; } else if (curVal == 1) { return true; }
return false; } }
|
利用dfs一次一次扩充岛屿,记录每一次扩充,当扩充到可以连接到另外一个岛屿时停止,但是这个方法会重复访问岛的中心部分,并且一个点会被多次访问(因为没有visited数组),时间复杂度偏高。
优化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| class Solution { private int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; public int shortestBridge(int[][] grid) { int n = grid.length; Queue<int[]> queue = new LinkedList<>(); boolean[][] visited = new boolean[n][n]; boolean found = false; for (int i = 0; i < n; i++) { if (found) break; for (int j = 0; j < n; j++) { if (grid[i][j] == 1) { dfsMarkIsland(grid, visited, queue, i, j); found = true; break; } } } int steps = 0; while (!queue.isEmpty()) { int size = queue.size(); for (int i = 0; i < size; i++) { int[] point = queue.poll(); int x = point[0], y = point[1]; for (int[] dir : directions) { int newX = x + dir[0]; int newY = y + dir[1]; if (newX >= 0 && newY >= 0 && newX < n && newY < n && !visited[newX][newY]) { if (grid[newX][newY] == 1) { return steps; } if (grid[newX][newY] == 0) { queue.offer(new int[]{newX, newY}); } visited[newX][newY] = true; } } } steps++; } return -1; }
private void dfsMarkIsland(int[][] grid, boolean[][] visited, Queue<int[]> queue, int x, int y) { int n = grid.length; visited[x][y] = true; queue.offer(new int[]{x, y}); for (int[] dir : directions) { int newX = x + dir[0]; int newY = y + dir[1]; if (newX >= 0 && newY >= 0 && newX < n && newY < n && !visited[newX][newY] && grid[newX][newY] == 1) { dfsMarkIsland(grid, visited, queue, newX, newY); } } } }
|
SCU某学院预推免机试题
最终擦边获得推免资格。
先暂停秋招,暂停刷题。
学院预推免机试系统仅支持C/C++语言,难度中等偏易。
第一题:寻找单身数
利用异或的特性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include<iostream> using namespace std;
int main(){ int n; int res = 0; int input; cin>>n; for(int i=0;i<n;i++){ cin>>input; res = res^input; } cout<<res<<endl; }
|
第二题:二叉树的层序遍历
本题需要自己根据输入构造二叉树,然后利用队列完成层序遍历即可。(比leetcode上的简单,因为这里不用分层)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include<iostream> #include<queue> using namespace std;
class Node{ public: int left; int right; int val; };
int main(){ int n; cin>>n; Node con[101]; for(int i=1;i<=n;i++){ Node node; node.val = i; con[i] = node; } int left,right; for(int i=1;i<=n;i++){ cin>>left>>right; con[i].left = left; con[i].right = right; } Node root = con[1]; int res[101]; int idx = 0; deque<Node> q; q.push_back(root); while(!q.empty()){ Node top = q.front(); q.pop_front(); res[idx++] = top.val; if(top.left!=-1)q.push_back(con[top.left]); if(top.right!=-1)q.push_back(con[top.right]); } for(int i=0;i<idx;i++){ cout<<res[i]<<" "; } }
|
第三题:成绩排序
本题涉及两个排序:对成绩的排序,对相同成绩的同学的姓名进行排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| #include<iostream> using namespace std;
class Student{ public: string name; int scores; };
bool compare_name(string name_1,string name_2); void sort(Student *students,int n,int *bucket);
int main(){ int n; Student students[101]; cin>>n; string input_name; int a,b,c; for(int i=1;i<=n;i++){ cin>>input_name; cin>>a>>b>>c; Student student; student.name = input_name; student.scores = a+b+c; students[i] = student; } int buckets[301][102]; for(int i=0;i<=300;i++){ buckets[i][101]=0; } for(int i=1;i<=n;i++){ Student student = students[i]; int scores = student.scores; int idx = buckets[scores][101]; buckets[scores][idx] = i; buckets[scores][101]++; } for(int i=300;i>=0;i--){ int amount = buckets[i][101]; if(amount>0){ if(amount>1){ sort(students,n,buckets[i]); } for(int j=0;j<amount;j++){ int student_idx = buckets[i][j]; cout<<students[student_idx].name<<endl; } } } return 0; }
void sort(Student *students,int n,int *bucket){ int size = bucket[101]; for(int i=size-1;i>0;i--){ for(int j=0;j<i;j++){ Student cur = students[bucket[j]]; Student next = students[bucket[j+1]]; if(compare_name(cur.name,next.name)==0){ int tmp = bucket[j]; bucket[j] = bucket[j+1]; bucket[j+1] = tmp; } } } }
bool compare_name(string name_1,string name_2){ int len_1 = name_1.length(); int len_2 = name_2.length(); if(len_1<=len_2){ string substring = name_2.substr(0,len_1); int tmp = name_1.compare(substring); if(tmp<0)return true; else return false; }else{ string substring = name_1.substr(0,len_2); int tmp = substring.compare(name_2); if(tmp<=0)return true; else return false; } }
|
a.compare(b)
返回的是一个整数
如果 a
小于 b
,返回一个负数。(a在字典序中排在前)
如果 a
等于 b
,返回 0
。
如果 a
大于 b
,返回一个正数。(b在字典序中排在后)
所以,其实程序中可以不用单独写一个compare_name
的函数,当时不太了解string.compare()
函数,所以额外写了一些没必要的操作。。。Anyways,AC了。
第四题:打印内存
输入:
一个正整数N,表示有N个数
N个数
输出:
依次输出这N个数每个数对应的内存
解:
无符号整数,4字节32位。
而内存使用16进制表示,一个16进制数用4位二进制表示。
那么一个无符号整数32位就需要8个16进制数来表示,所以我们直接4位一组将目标数分割提取出来(位运算),将其转换为8个16进制数即可,然后根据小端存储的规则将其打印。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| #include<iostream> using namespace std;
void fun(int num); int main(){
int n; cin>>n; for(int i=1;i<=n;i++){ int input; cin>>input; fun(input); } }
void fun(int num){ int helper[9]; helper[1] = 0x0000000f; helper[2] = 0x000000f0; helper[3] = 0x00000f00; helper[4] = 0x0000f000; helper[5] = 0x000f0000; helper[6] = 0x00f00000; helper[7] = 0x0f000000; helper[8] = 0xf0000000; int res[9]; for(int i=1;i<=8;i++){ int tmp = num&helper[i]; tmp = tmp >> (i-1)*4; res[i] = tmp; } for(int i=1;i<=4;i++){ int idx_1 = i*2; int idx_2 = idx_1 - 1;
if(res[idx_1]<10){ cout<<res[idx_1]; }else{ if(res[idx_1]==10)cout<<"A"; if(res[idx_1]==11)cout<<"B"; if(res[idx_1]==12)cout<<"C"; if(res[idx_1]==13)cout<<"D"; if(res[idx_1]==14)cout<<"E"; if(res[idx_1]==15)cout<<"F"; } if(res[idx_2]<10){ cout<<res[idx_2]; }else{ if(res[idx_2]==10)cout<<"A"; if(res[idx_2]==11)cout<<"B"; if(res[idx_2]==12)cout<<"C"; if(res[idx_2]==13)cout<<"D"; if(res[idx_2]==14)cout<<"E"; if(res[idx_2]==15)cout<<"F"; } if(i==4){ cout<<endl; } else cout<<" "; } }
|