OJ算法

蛇形矩阵

    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();
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值