Acwing 4204. 构造矩阵
请你构造一个 n×n 的整数矩阵。
要求,矩阵满足下列所有条件:
- 矩阵中的所有元素的取值范围为 [0,n−1]。
- 矩阵主对角线上的所有元素都为 0。主对角线是指从左上角到右下角这一斜线方向的对角线。
- 该矩阵是对称矩阵。对称矩阵是指以主对角线为对称轴,各元素对应相等的矩阵。
- 同一行上的所有元素两两不同。
- 同一列上的所有元素两两不同。
输入格式
一个整数 n。
输出格式
共 n 行,每行 n个空格隔开的整数,表示整个矩阵。
如果方案不唯一,输出任意合理方案均可。
数据范围
前三个测试点满足 2≤n≤10。
所有测试点满足 2≤n≤1000,n 保证是偶数。
输入样例1:
2
输出样例1:
0 1 1 0
输入样例2:
4
输出样例2:
0 1 3 2
1 0 2 3
3 2 0 1
2 3 1 0
思路:
考虑n - 1行列如何构造,例如n = 4
构造3行3列得
1 2 3
2 3 1
3 1 2
将对角线元素添加到行尾和列为,并替换对角线元素为0,得
0 2 3 1
2 0 1 3
3 1 0 2
1 3 2 0
满足要求
import java.util.*;import java.io.*;public class Main {public static void main(String[] sss) throws IOException{BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[][] res = new int[n][n];for (int i = 0; i < n - 1; i++) {for (int j = 0; j < n - 1; j++) {res[i][j] = (i + j) % (n - 1) + 1;}}for (int i = 0; i < n - 1; i++) {res[i][n - 1] = res[n - 1][i] = res[i][i];res[i][i] = 0;}for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++)bw.write(res[i][j] + " ");bw.write("\n");}bw.close();// br.close();}}
767. 重构字符串
给定一个字符串 s ,检查是否能重新排布其中的字母,使得两相邻的字符不同。
返回 s 的任意可能的重新排列。若不可行,返回空字符串 “” 。
示例 1:
输入: s = “aab” 输出: “aba”
示例 2:
输入: s = “aaab” 输出: “”
提示:
- 1 <= s.length <= 500
- s 只包含小写字母
思路:
构造,按字符出现次数从大到小排序,若存在cnt(c) > (n + 1) / 2,说明无解
否则,插空放即可
class Solution {public String reorganizeString(String s) {int n = s.length();int[][] cnt = new int[26][2];for (int i = 0; i < s.length(); i++) {cnt[s.charAt(i) - 'a'][0]++;}for (int i = 0; i < 26; i++)cnt[i][1] = i;Arrays.sort(cnt, (o1, o2) -> (o2[0] - o1[0]));if (cnt[0][0] > (n + 1) / 2)return "";char[] res = new char[n];Arrays.fill(res, '0');int idx = 0;for (int i = 0; i < 2; i++) {int j = i;while (j < n && cnt[idx][0] > 0) {res[j] = (char)(cnt[idx][1] + 'a');j += 2;cnt[idx][0]--;if (cnt[idx][0] == 0)idx++;}}return new String(res);}}
358. K 距离间隔重排字符串
给你一个非空的字符串 s 和一个整数 k ,你要将这个字符串 s 中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离 至少 为 k 。如果无法做到,请返回一个空字符串 “”。
示例 1:
输入: s = “aabbcc”, k = 3 输出: “abcabc” 解释: 相同的字母在新的字符串中间隔至少 3 个单位距离。
示例 2:
输入: s = “aaabc”, k = 3 输出: “” 解释: 没有办法找到可能的重排结果。
示例 3:
输入: s = “aaadbbcc”, k = 2 输出: “abacabcd” 解释: 相同的字母在新的字符串中间隔至少 2 个单位距离。
提示:
- 1 <= s.length <= 3 * 105
- s 仅由小写英文字母组成
- 0 <= k <= s.length
思路:
相较于767,k = 2 -> k不定
优先队列 + 队列
class Solution {public String rearrangeString(String s, int k) {if (k <= 1)return s;if (k > 26)return "";int[][] cnt = new int[26][2];for (int i = 0; i < 26; i++)cnt[i][1] = i;int n = s.length();for (int i = 0; i < n; i++) {cnt[s.charAt(i) - 'a'][0] ++ ;}PriorityQueue<int[]> q = new PriorityQueue<>((o1, o2) -> (o2[0] == o1[0] ? o1[1] - o2[1] : o2[0] - o1[0]));for (int i = 0; i < 26; i++)if (cnt[i][0] != 0)q.offer(cnt[i]);Queue<int[]> q2 = new LinkedList<>();int sum = n;StringBuilder sb = new StringBuilder();while (!q.isEmpty()) {int size = q.size();if (size < Math.min(k, sum))return "";int c = Math.min(k, sum);sum -= c;while (c-- > 0) {q2.offer(q.poll());}while (!q2.isEmpty()) {int[] u = q2.poll();sb.append((char)(u[1] + 'a'));u[0]--;if (u[0] > 0)q.offer(u);}}return sb.toString();}}
// APIclass Solution {public String rearrangeString(String s, int k) {if(k <= 1)return s;Map<Character, Integer> map = new HashMap<>();int n = s.length();for (int i = 0; i < n; i++)map.merge(s.charAt(i), 1, Integer::sum);PriorityQueue<Map.Entry<Character, Integer>> maxHeap = new PriorityQueue<>((o1, o2) -> (o2.getValue() - o1.getValue()));maxHeap.addAll(map.entrySet());Queue<Map.Entry<Character, Integer>> q = new LinkedList<>();StringBuilder sb = new StringBuilder();while (!maxHeap.isEmpty()) {var cur = maxHeap.poll();sb.append(cur.getKey());cur.setValue(cur.getValue() - 1);q.offer(cur);if (q.size() == k) {cur = q.poll();if (cur.getValue() > 0)maxHeap.offer(cur);}}return sb.length() == n ? sb.toString() : "";}}
