蛇形矩阵
private static String serpentineMatrix(int n) {
StringBuilder builder = new StringBuilder();
for (int i = 1; i <= n; i++) {
// 每一行的第一个元素是(i-1)*i/2+1
// 每一行的元素个数是n-i
// 初始间隔是i+1,之后每一个间隔比上一个间隔多1,之后的每个元素是前一个元素加上间隔
for (int j = 1, start = (i - 1) * i / 2 + 1, step = i + 1; j <= n - i + 1; j++, start += step, step++) {
builder.append(start).append(' ');
}
// 设置换行符
builder.setCharAt(builder.length()-1, '\n');
}
return builder.toString();
}
合唱队
/**
* <pre>
* 解题思路
* 乍一看这道题好像无从下手?难不成要枚举出所有的情况才能得出结果。一般来说是不会有那种枚举所有情况的题的。
* 实际上这是一道简单动态规划的题。但是一眼看上去不是很直观。题目所谓的合唱队形就是一个最长上升子序列的拼接。
* 只要求出从队列首到位置 i 的最长上升子序列长度加上从队尾开始到位置 i 的最长上升子序列的长度就能求出合唱队
* 形的总长度。 我们还知道总的人数,减一下就能得出要出列的人数了。
*
* 求最长上升子序列
* 现在有一个序列,要求他的最长上升子序列。直观上并不是很好求得,反过来看的话就能比较好理解:
* 现在对于总序列里的第i个元素来说,包含元素i的最长子序列是多少呢?如果i前面有能构成最长上升序列的(设它为j),
* 而且i数值比j大,那很显然到第i个元素(包含元素i)的最长子序列是到第j个元素的最长子序列+1;否则到第i个元素
* (包含元素i)的最长子序列就是是1。因为前面没有比他更小的了,只有自身构成一个子序列。
* </pre>
*
* @param arr
* @return
*/
private static int countChorus(int[] arr) {
int[] ltr = getRiseLongestSequenceLeftToRight(arr);
int[] rtl = getRiseLongestSequenceRightToLeft(arr);
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
if (max < ltr[i] + rtl[i]) {
max = ltr[i] + rtl[i] - 1;
}
}
return arr.length - max;
}
private static int[] getRiseLongestSequenceLeftToRight(int[] arr) {
int[] ltr = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
ltr[i] = 1;
for (int j = 0; j < i; j++) {
if (arr[i] > arr[j] && ltr[i] <= ltr[j]) {
ltr[i] = ltr[j] + 1;
}
}
}
return ltr;
}
private static int[] getRiseLongestSequenceRightToLeft(int[] arr) {
int[] rtl = new int[arr.length];
for (int i = arr.length - 1; i >= 0; i--) {
rtl[i] = 1;
for (int j = arr.length - 1; j > i; j--) {
if (arr[i] > arr[j] && rtl[i] <= rtl[j]) {
rtl[i] = rtl[j] + 1;
}
}
}
return rtl;
}
计票统计
while (scanner.hasNext()) {
int n = scanner.nextInt();
String[] names = new String[n + 1];
Map<String, Integer> map = new HashMap<>(n);
for (int i = 0; i < n; i++) {
names[i] = scanner.next();
map.put(names[i], 0);
}
names[n] = "Invalid";
map.put(names[n], 0);
int v = scanner.nextInt();
while ((--v) >= 0) {
String s = scanner.next();
if (map.containsKey(s)) {
map.put(s, map.get(s) + 1);
} else {
map.put(names[n], map.get(names[n]) + 1);
}
}
StringBuilder builder = new StringBuilder();
for (String s: names ) {
builder.append(s).append(" : ").append(map.get(s)).append('\n');
}
System.out.print(builder.toString());
}
句子逆序
private static String reverseSentence(String str) {
char[] chars = str.toCharArray();
// 翻转整个句子
reverse(chars, 0, chars.length - 1);
for (int i = 0, j; i < chars.length; i = j + 1) {
// 找从i位置开始后的第一个非空白字符
while (i < chars.length && chars[i] ==' ' ) {
i++;
}
j = i + 1;
// 找i位置之后的第一个空白字符
while (j < chars.length && chars[j] != ' ') {
j++;
}
reverse(chars, i, j - 1);
}
return new String(chars);
}
/**
* 字符数组翻转
* @param str
* @param start
* @param end
*/
private static void reverse(char[] str, int start, int end) {
char tmp;
while (start < end) {
tmp = str[start];
str[start] = str[end];
str[end] = tmp;
start++;
end--;
}
}
单词倒排
private static String reverse(String s) {
char[] chars = new char[s.length()];
int pos = 0;
// 下面进行字符串的压缩,去掉前导各后面的空格,中间单词间只保留一个空格
for (int i = 0; i < s.length();) {
// 从开始的i位置开始找第一个非空白字符
while (i < s.length() && s.charAt(i) == ' ') {
i++;
}
// 从开始的i位置开始找第一个空白字符
while (i < s.length() && s.charAt(i) != ' ') {
chars[pos] = s.charAt(i);
pos++;
i++;
}
// 此时i位置是一个空白字符,说明i后面还可能有非空白字符
// 所以需要添加一个空白字符作为分隔
if (i< s.length()) {
chars[pos] = ' ';
pos++;
}
}
// 最后压缩后最后一个字符的位置
pos--;
// System.out.println("|" + new String(chars, 0, pos+1) + "|");
// 将整个个字符串翻转一次
reverse(chars, 0, pos);
// 下面找每个单词进行翻转
for(int i = 0, j; i <= pos; i++) {
j = i;
// 找i从开始的第一个空白字符
while (i <= pos && chars[i] != ' ') {
i++;
}
// 进行单词翻转
reverse(chars, j, i - 1);
}
return new String(chars, 0, pos + 1);
}
private static void reverse(char[] arr, int beg, int end) {
char tmp;
while (beg < end) {
tmp = arr[beg];
arr[beg] = arr[end];
arr[end] = tmp;
beg++;
end--;
}
}
超长正整数相加
/**
* Author: 王俊超
* Date: 2015-12-24 17:18
* All Rights Reserved !!!
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data.txt"));
while (scanner.hasNext()) {
String n = scanner.next();
String m = scanner.next();
// 【1】方法一
System.out.println(addLongInteger(n, m));
// 【2】方法二
// BigInteger bi1 = new BigInteger(n);
// BigInteger bi2 = new BigInteger(m);
// System.out.println(bi1.add(bi2));
}
scanner.close();
}
/**
* 大整数相加,ns、ms都不小于0
*
* @param ns 数字
* @param ms 数字
* @return 结果
*/
private static String addLongInteger(String ns, String ms) {
int[] n = getNumber(ns);
int[] m = getNumber(ms);
// 进行计算
int[] r = add(m, n);
return toNumber(r);
}
/**
* 两个不小于零的整数相加
*
* @param m 整数
* @param n 整数
* @return 结果
*/
private static int[] add(int[] m, int[] n) {
// System.out.println(Arrays.toString(n) +"\n"+ Arrays.toString(m));
// 保证n不小于m
if (m.length > n.length) {
int[] t = m;
m = n;
n = t;
}
// 结果的最大长度
int[] r = new int[n.length + 1];
// 来自低位的进位
int c = 0;
for (int i = 0; i < m.length; i++) {
r[i] = m[i] + n[i] + c;
c = r[i] / 10;
r[i] %= 10;
}
// 计算余下的部分
for (int i = m.length; i < n.length; i++) {
r[i] = n[i] + c;
c = r[i] / 10;
r[i] %= 10;
}
// System.out.println(Arrays.toString(n) +"\n"+ Arrays.toString(m) + "\n" + Arrays.toString(r));
// 最后还有进位
if (c != 0) {
r[r.length - 1] = c;
return r;
}
// 没有进位
else {
int[] ret = new int[r.length - 1];
System.arraycopy(r, 0, ret, 0, ret.length);
return ret;
}
}
/**
* 将整数字符串表示成整数数组【不包含符号位】
*
* @param n 整数字符串
* @return 整数数组 下标从小到大表示数位的从低到高
*/
private static int[] getNumber(String n) {
int[] r = new int[n.length()];
for (int i = 0; i < r.length; i++) {
r[i] = n.charAt(n.length() - i - 1) - '0';
}
return r;
}
/**
* 将数组表示的整数转换成字符串
*
* @param r 整数
* @return 字符串表示的整数
*/
private static String toNumber(int[] r) {
if (r == null) {
return null;
}
StringBuilder b = new StringBuilder(r.length);
for (int i = r.length - 1; i >= 0; i--) {
b.append(r[i]);
}
return b.toString();
}
}