算法题-20200409

/**
 给定一个int[n] a,其在下标为0到k上以及k到n-1上都是单调递增,且a[n-1]小于a[0],求k
 */
public class BBB {

    public static int findK(int[] source) {
        int length = source.length;
        if (length <= 2) {
            return 0;
        }
        //初始下标
        int left = 0;
        int right = length - 1;
        int startValue = source[0];
        int mid = 0;
        int k = 0;
        //二分
        while (left < right) {
            //中间下标
            mid = (right - left) / 2 + left;
            //最后剩下两个元素时,大的那个就是k
            if (right == left + 1) {
                k = source[left] > source[right] ? left : right;
                break;
            }
            //若右边的区域的第一个数小于起始值,说明k在左边,反之,在右边
            if (source[mid + 1] < startValue) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        //循环退出后,若左右坐标相同,说明这个坐标就是k
        return left == right ? left : k;
    }

    public static void main(String[] args) {
//        int[] a = {80, 90, 100, 4, 7, 9};
//        int[] a = {20, 40, 50, 60, 200, 9};
        int[] a = {90, 3, 4, 5, 7, 9};
        System.out.println(findK(a));
    }
}
/**
给定⼀一个 ⽆无向图 包含 N 个节点和 M 条边, 每条边 Mi 的代价为 Ci 。图中⼀一条 路路径的惩罚是指对该路路径上所有边的代价 Ci 执⾏行行位运算或(bitwise OR)操 作得到的。假如⼀一条路路径上包含了了边 M1,M2,M3 ... ... ,Mk,那么对应的惩 罚就是 C1 OR C2 OR C3 OR ... OR Ck。(OR代表位运算或,即 “|” )
问题:给定图上两个节点 start 和 end,找到从 start 到 end 的所有路路径中惩罚 值最⼩小的路路径,对应的最⼩小惩罚值作为结果返回。如果路路径不不存在就返回 -1。
注意:任意两个节点之间最多存在⼀一条边,图中可能存在有环路路。
参数含义:
n:节点总数;节点编号从 1 开始,⼀一直到 n,共有 n 个; edges:⽆无向图的边;edges[i] 表示边Mi,其中 edges[i][0] 和 edges[i][1] 是Mi的两个节点的编号,edges[i][2] 是Mi对应的代价 Ci; start 和 end:路路径的开始和结束节点编号
*/
public class FindsNodePunish {

    static int beautifulPath(int n, int[][] edges, int start, int end) {
        Map<Integer, Map<Integer, Integer>> edgesMap = getEdgesMap(n, edges);
        int result = minPath(edgesMap, start, end);
        return result == Integer.MAX_VALUE ? -1 : result;
    }

    //获得点到其它的距离集合
    private static Map<Integer, Map<Integer, Integer>> getEdgesMap(int n, int[][] edges) {
        Map<Integer, Map<Integer, Integer>> map = new HashMap<>(2 * n);
        List<int[]> list = new ArrayList<>(n);
        Collections.addAll(list, edges);
        list.forEach(e -> {
            int start = e[0];
            int end = e[1];
            int distance = e[2];
            map.computeIfAbsent(start, k -> new HashMap<Integer, Integer>(n));
            map.get(start).merge(end, distance, (a, b) -> b < a ? b : a);
        });
        return map;
    }

    //深度优先,获取所有可能的路径及惩罚
    private static int minPath(Map<Integer, Map<Integer, Integer>> edgesMap, int start, int end) {
        Map<Integer, Integer> startMap = edgesMap.get(start);
        int result = Integer.MAX_VALUE;
        for (Map.Entry<Integer, Integer> e : startMap.entrySet()) {
            int next = e.getKey();
            int path = e.getValue();
            if (next != end) {
                edgesMap.remove(start);
                path = path | minPath(edgesMap, next, end);
                edgesMap.put(start, startMap);
            }
            if (path < result) {
                result = path;
            }
        }
        return result;
    }

    public static void main(String[] args) {
        int[][] edges = {{1, 2, 1}, {2, 3, 3}, {1, 3, 100}};
        System.out.println(beautifulPath(3, edges, 1, 3));
    }
}
/**
 * 给定⼀一个按开始时间从⼩小到⼤大排序的时间区间集合,请将重叠的区间合并。
 * 时 间区间集合⽤用⼀一个⼆二维数组表示,⼆二维数组的每⼀一⾏行行表示⼀一个时间区间(闭区 间),
 * 其中 0 位置元素表示时间区间开始,1 位置元素表示时间区间结束。
 */
public class CombineTime {
    static int[][] merge(int[][] intervals) {
        if (intervals.length == 0) {
            return null;
        }
        int[][] midleValue = new int[intervals.length][];
        //返回区间的偏移量
        int returnValueIndex = 0;
        //循环,每个区间跟后一个区间比较,若右闭大于左起,合并,合并后的右闭取两者的右闭中大的
        for (int i = 0; i < intervals.length - 1; i++) {
            int[] leftOne = midleValue[returnValueIndex];
            if (i == 0) {
                //初始值,取给定数组的
                leftOne = intervals[0];
            }
            int[] rightOne = intervals[i + 1];
            if (leftOne[1] >= rightOne[0]) {
                //需要合并
                int[] combineOne = new int[2];
                combineOne[0] = leftOne[0];
                combineOne[1] = leftOne[1] > rightOne[1] ? leftOne[1] : rightOne[1];
                midleValue[returnValueIndex] = combineOne;
            } else {
                //直接放入返回值
                midleValue[returnValueIndex++] = leftOne;
                midleValue[returnValueIndex] = rightOne;
            }
        }
        //去掉null值
        int[][] returnValue = new int[returnValueIndex + 1][];
        for (int i = 0; i <= returnValueIndex; i++) {
            returnValue[i] = midleValue[i];
        }
        return returnValue;
    }

    public static void main(String[] args) {
        int[][] intervals = {{1, 3}, {2, 6}, {8, 10}, {15, 18}};
        System.out.println(Arrays.deepToString(merge(intervals)));
    }

}
/**
 * 给定⼀一个⾮非空字符串串 s 和⼀一个缩写 abbr,请校验它们是否匹配。
 * 假设字符串串中只包含⼩小写字⺟母,缩写中只包含⼩小写字⺟母和数字。
 * 缩写中的数字 表示其缩略略的字符数;连续多位数字表示⼀一个多位数
 */
public class ValidAbbr {
    static boolean valid(String word, String abbr) {
        char[] words = word.toCharArray();
        char[] abbrs = abbr.toCharArray();
        //从缩写中读取,如果是英文,则去字符串数组中匹配,如果是数字,则偏移数字量
        String numberTemp = "";
        int wordsIndex = 0;
        for (char temp : abbrs) {
            if (Character.isDigit(temp)) {
                numberTemp += temp;
                continue;
            } else {
                //字母
                if (!"".equals(numberTemp)) {
                    //偏移
                    wordsIndex += Integer.parseInt(numberTemp);
                    numberTemp = "";
                }
                if (wordsIndex >= words.length) {
                    return false;
                }
                //是否匹配
                if (temp == words[wordsIndex]) {
                    wordsIndex++;
                    continue;
                } else {
                    return false;
                }
            }
        }
        return wordsIndex == words.length;
    }

    public static void main(String[] args) {
        System.out.println(valid("internationalization", "i12iz4n"));
    }
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值