4.20 bilibili笔试 JAVA
第一题 找牛牛
青牛小学一年一度的六一儿童节开始了。现在牛牛们围成一圈坐在草地上,为了方便,我们把牛牛们编号为牛1,牛2,牛3,牛n。
其中牛1与牛2相邻,牛2与牛3相邻,牛n和牛1相邻。
为了更好的安排接下来的活动,牛老师很好奇:从这些牛中选出几只相邻的牛,总共有多少种不同的方案?
我们认为两个方案不同,当且仅当两种选法选出的牛个数不同或选出的牛的编号不完全相同
输入描述
输入一个整数n,表示牛的个数
输出描述
输出一个整数n,表示方案数
示例1
输入
2
输出
3
解释
环为1,2可以选择(1},{2},{1.2}
示例2
输入
4
输出
13
解释
环为1,2,3,4可以选择(1}, {2, {3}, {4},{1,2}, {2,3}, {3, 4}, {4, 1},{1,2,3},{2,3,4},{3,4,1} {4,1,2}{1,2,3,4}共13种情况
思路与代码
基本思路:观察问题,我们需要计算从n头牛中选出若干头相邻的牛的方案数。由于牛是围成一圈的,这意味着我们可以从任意一头牛开始数。
分解问题:
- 不特殊的方案:首先考虑所有的牛都不同时被选中的情况。在这种情况下,我们可以选择任意一头牛作为起点(有n种选择),然后选择从这头牛开始的任意连续数量的牛(1到n-1种选择,因为如果选择了n头,那就是特殊情况了)。因此,这部分的方案数为 (n *(n-1)。
- 特殊方案:所有的牛都被选中的情况。这是一个特殊的方案,因为不管从哪头牛开始数,选出的都是全部的牛。这种情况下只有1种方案。
总结方案数:将上述两种情况相加,得到的总方案数就是 n*(n-1)+1。
因此代码将n*(n-1)+1直接输出就可以了。
如果增加难度,要求输出各个方案,则代码如下:
// 自己写的,比较复杂 import java.util.*; public class zhao_niu { public List<List<Integer>> xianglin(int n) { List<List<Integer>> result = new ArrayList<>(); int[] nums = new int[2*n-2]; for (int i = 0; i < n; i++) nums[i] = i + 1; for (int i = 0; i < n-2; i++) nums[n+i] = nums[i]; for (int j = 0; j < n; j++){ result.add(new ArrayList<>()); for (int i = 0; i < n - 1; i++) { List<Integer> list = new ArrayList<>(result.get(j*n+i)); list.add(nums[j+i]); result.add(list); } } for (int i = 0; i < n; i++){ result.remove(i*(n-1)); } List<Integer> list = new ArrayList<>(); for (int i = 0; i < n; i++){ list.add(nums[i]); } result.add(list); return result; } public static void main(String[] args){ Scanner in = new Scanner(System.in); int n = in.nextInt(); zhao_niu obj = new zhao_niu(); List<List<Integer>> result = obj.xianglin(n); for (int i = 0; i < result.size(); i++){ System.out.println(result.get(i)); } // System.out.println(n*(n-1) + 1); } }
// 别人写的 import java.util.*; public class zhao_niu2 { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); // 输入小孩的个数 // 输出各个方案 List<List<Integer>> schemes = findSchemes(n); for (List<Integer> scheme : schemes) { System.out.println(scheme); } } // 寻找所有方案的方法 public static List<List<Integer>> findSchemes(int n) { // 存储所有方案的列表 List<List<Integer>> schemes = new ArrayList<>(); // 遍历每个小孩,生成单独的方案 for (int i = 1; i <= n; i++) { List<Integer> scheme = new ArrayList<>(); scheme.add(i); schemes.add(scheme); } // 逐步增加小孩数量,生成更长的方案 for (int len = 2; len <= n-1; len++) { // 从每个小孩开始,生成具有特定长度的方案 for (int start = 1; start <= n; start++) { List<Integer> scheme = new ArrayList<>(); // 构建方案中的小孩编号 for (int j = start; j < start + len; j++) { int num = j > n ? j - n : j; // 处理小孩编号循环的情况 scheme.add(num); } // 将生成的方案加入方案列表 schemes.add(scheme); } } List<Integer> scheme = new ArrayList<>(); for (int i = 1; i <= n; i++){ scheme.add(i); } schemes.add(scheme); // 返回所有生成的方案列表 return schemes; } }
第二题 翻转字符串
给出一个长度为n的字符串s和一个整数k,现在请你依次按照i= 1,2,.....n-k+1的顺序求出以下操作得到的字符串将字符串s的第i个字符至第i+k- 1之间的所有字符翻转。 求出最终状态的字符串。 例如:n是5,是3,s是"hello"。 i=1时,翻转[1,3]之间的字符,得到"lehlo" i=2时,翻转 [2,4]之间的字符,得到"llheo" i=3时,翻转 [3,5]之间的字符,得到"lloeh" 因此,最终的s为"lloeh"。
输入描述
第一行输入正整数n,k。
第二行输入仅由小写字母构成的字符串s。 2≤k≤n≤2x10^5
输出描述
输出s经过翻转后的最终状态。
示例1
输入
5 3
hello
输出
lloeh
示例2
输入
8 5
nowcoder
输出
odernowc
思路与代码
跟上一题类似,需要想象一下这个过程,从第k个字符被翻转,更多是逻辑吧,思路如下:
- 操作次数:首先,注意到对于每个
i从 1 到n-k+1,我们会进行n-k+1次翻转操作。 - 奇偶性分析:对于任何给定的一段长度,连续两次完全相同的翻转将会抵消,即字符序列会恢复到翻转前的状态。因此,如果一个字符被翻转奇数次,它的最终位置会与初始位置不同;如果被翻转偶数次,它的最终位置会与初始位置相同。
- 翻转的影响范围:在这个问题中,每次翻转的影响范围是固定长度的(k个字符),并且随着
i的递增,这个翻转窗口在字符串上滑动。 - 特定位置的翻转次数
- 对于字符串
s的前k-1个字符和后k-1个字符,随着翻转窗口的滑动,它们的翻转次数会从 1 逐渐增加到k,然后再逐渐减少到 1。这意味着,如果n-k是奇数,则这部分字符的翻转次数为奇数;如果n-k是偶数,则翻转次数为偶数。 - 对于字符串的其余部分,即从第
k个字符到第n-k个字符,每个字符会被翻转k次,这是一个固定的偶数次。
暴力解法只能过30%。
import java.util.*; public class fan_zhuan { public String reverse_string(int n, int k, String s){ char[] ch = s.toCharArray(); int left = 0; int right = n - k; for (int i = 0; i < n - k + 1; i++){ reverse(ch, i, i+k-1); } return new String(ch); } public void reverse(char[] ch, int start, int end){ for (; start < end; start++, end--){ char tmp = ch[start]; ch[start] = ch[end]; ch[end] = tmp; } } public static void main(String[] args){ Scanner in = new Scanner(System.in); int n = in.nextInt(); int k = in.nextInt(); in.nextLine(); String s = in.nextLine(); fan_zhuan obj = new fan_zhuan(); String after = obj.reverse_string(n, k, s); System.out.println(after); } }
找规律的解法:
import java.util.Scanner; public class fanzhuan3 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int k = scanner.nextInt(); scanner.nextLine(); // Consume the newline character after reading integer input String s = scanner.nextLine(); if ((n - k) % 2 != 0) { System.out.println(s.substring(k - 1) + s.substring(0, k - 1)); } else { StringBuilder reversedSubstring = new StringBuilder(s.substring(0, k - 1)); System.out.println(s.substring(k - 1) + reversedSubstring.reverse().toString()); } scanner.close(); } }
浙公网安备 33010602011771号