数据结构算法题(小牛试刀)

数据结构是为算法服务的,算法是作用在特定的数据结构之上的

 

指向效率是评价算法好坏的一个非常重要的指标,衡量的方法常用的是时间复杂度的空间复杂度分析。复杂的分析有事后分析法和算法执行效率估算法

  • 最常见的使用是大O复杂度表示法,表示的是代码的执行时间随着数据规模的增大的变化趋势

数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图

算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法

1.进制转换

  • 数制转换

    10进制转化其他进制对应的方法,参数n(原10进制数据)返回值
    10进制转2进制Integer.toBinaryString(n);二进制字符串
    10进制转8进制Integer.toOctalString(n);八进制字符串
    10进制转16进制Integer.toHexString(n);十六进制字符串
    10进制转r进制(r表示任意)Integet.toString(n,r);r进制字符串
  • 其他进制转十进制

    Integer.valurof(String s,int radix):Integer      radix进制的字符串转十进制

直接将0xAA不能转化为十进制,需要去除前面的0x

Scanner sc = new Scanner(System.in);
    while (sc.hasNextLine()) {
        String str = sc.nextLine();
        //简化写法System.out.println(Integer.valueOf(str.substring(2), 16).toString());
        String ss = str.substring(2);
        int kk = Integer.valueOf(ss, 16);
        System.out.println(kk);
}
    sc.close();

2.两数之和

直观思路:两层for循环,暴力匹配

public static void main(String[] args) {
        String str = "[3,2,4],6";
        String[] arr = str.split("[\\[,\\]]");
        int[] brr = Arrays.stream(arr).filter(t -> t.trim().length() > 0).mapToInt(Integer::valueOf).toArray();
        int[] crr = Arrays.copyOf(brr, brr.length - 1);
        int target = brr[brr.length - 1];
        System.out.println(target);
        int[] res = twoSum(crr, target);
        System.out.println(Arrays.toString(res));
    }
​
    public static int[] twoSum(int[] arr, int target) {
        int[] res = new int[2];
        for (int i = 0; i < arr.length; i++) {
            for (int k = 0; k < arr.length; k++) {
                if (i < k && target == arr[i] + arr[k]) {
                    res[0] = i + 1;
                    res[1] = k + 1;
                }
            }
        }
        return res;
    }

问题:时间复杂度O(n^2),而且还有无效的循环

优化:思路:获取一个数据a后,查找的数据应该是确定的,只要简化查找次数则可以降低时间复杂度

查找数据时间复杂度最低还是hashmap,选择key存储具体数据,使用value存储对应的序号

public int[] twoSum(int[] arr,int terget){
    //解算法题目时,要求直接使用具体类,不要考虑面向对象的问题
    HashMap<Integer,Integer> map = new HashMap<>();
    for(int i = 0;i < arr.length;i++)
        map.put(arr[i],i);
    int[] res = new int[2];
    for(int i = 0;i < arr.length;i++){
        if(map.containsKey(target-arr[i])){
            if(map.get(arr[i]) < map.get(target - arr[i])){
                res[0] = map.get(arr[i] + 1);
                res[1] = map.get(target-arr[i] +1);
                break;
            }
        }
    }
}

3.明明的随机数

Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
TreeSet<Integer> set = new TreeSet<>();
for(int i = 0;i < num;i++)
    set.add(sc.nextInt());
sc.close();
System.out.println(set.size());
for(Integer tmp : set)
    System.out.print(tmp+" ");

4.字符个数统计

Scanner sc = new Scanner(System.in);
HashSet<Character> set = new HashSet<>();
if (sc.hasNextLine()) {
    String str = sc.nextLine();
    for (char x : str.toCharArray()) {
        if (x < 128)
            set.add(x);
    }
}
sc.close();
System.out.println(set.size());

扩展:按照出现次数倒序输出

  • 除非答题中已经提示自定义类,否则一般不要考虑使用自定义类型的方法

  • 需要存储字符和对应的 出现次数,考虑使用Map

Scanner sc = new Scanner(System.in);
String str = sc.next();
HashMap<Character, Integer> map = new HashMap<>();
for (char tmp : str.toCharArray()) {
    int count = 1;
    if (map.containsKey(tmp)) {
        count = map.get(tmp) + 1;
    }
    map.put(tmp, count);
}
sc.close();
TreeSet<Entry<Character, Integer>> set = new TreeSet<>(new Comparator<Entry<Character, Integer>>() {
    @Override
    public int compare(Entry<Character, Integer> o1, Entry<Character, Integer> o2) {
        int res = o2.getValue().compareTo(o2.getValue());
        if (res == 0)
            res = o1.getKey().compareTo(o2.getKey());
        return res;
    }
});
set.addAll(map.entrySet());
System.out.println(set);

5.跳台阶

一只青蛙一次可以调跳上一级台阶,也可以跳上两级,求该青蛙跳上一个n级台阶总共有多少种跳法,先后次序不同算不同的结果

递归编程实现

public static void main(String[] args){
    int res = jump(20);
    System.out.println(res);
}
public int jump(int targer){
    if(targer == 1)
        return 1;
    if(targer == 2)
        return 2;
    return jump(target -1)+jump(target - 2);
}

时间复杂度为O(2^n),问题在于重复计算,引入Map可以记录以前的计算结果,从而减小计算次数

当计算f(18)时首先到Map中查找18对应的值,如果没有对应的值,则进行计算,计算完成后将计算结果 插入Map,供后续使用

public class A1 {
    private HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
​
    public static void main(String[] args) {
        A1 aa = new A1();
        int res = aa.jump(10);
        System.out.println(res);
    }
​
    public int jump(int target) {
        if (map.containsKey(target))
            return map.get(target);
        else {
            int res = 0;
            if (target == 1)
                res = 1;
            else if (target == 2)
                res = 2;
            else
                res = jump(target - 1) + jump(target - 2);
            map.put(target, res);
            return res;
        }
    }
​
}

map的输出为

[map={1=1, 2=2, 3=3, 4=5, 5=8, 6=13, 7=21, 8=34, 9=55, 10=89, 11=144, 12=233, 13=377, 14=610, 15=987, 16=1597, 17=2584, 18=4181, 19=6765, 20=10946}]

从小往大计算:动态规划

从key发现f(n) = f(n-1) + f(n-2)可以使用数组存储历史数据,从前向后推

public int jump(int target){
    int x1 = 0;
    int x2 = 0;
    int res = 0;
    for(int i = 1;i < target;i++){
        if(i == 1){
            x1 = 1;
            continue;
        }else if(i == 2){
            x2 = 2;
            continue;
        }
        res = x1 + x2;
        x1 = x2;
        x2 =res;
    }
    return res;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值