算法——常见的算法题

【一】常见的api使用

toCharArray() //get char array of a String
Arrays.sort()  //sort an array
Arrays.toString(char[] a) //convert to string
charAt(int x) //get a char at the specific index
length() //string length
length //array size 
substring(int beginIndex) 
substring(int beginIndex, int endIndex)
Integer.valueOf()//string to integer
String.valueOf()/integer to string

PriorityQueue插入保持内部有序:
PriorityQueue<Integer> heap = new PriorityQueue<>();
字符进行大小写转换:
Character.toUpperCase(c)
Character.toLowerCase(c);

常见api进行10,2,8,16进制的转换:
//十进制转二进制
 System.out.println(Integer.toBinaryString(10));
//十进制转八进制
 System.out.println(Integer.toOctalString(10));
 //十进制转十六进制
 System.out.println(Integer.toHexString(10));
// 其他进制转换为十进制
Integer.parseInt(String s ,int radix)

【二】全排序


public class Main {
    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] array = new int[n];
        for (int i = 0; i < array.length; i++) {
            array[i] = scanner.nextInt();
        }

        List<Integer[]> list = new ArrayList<>();
        getData(list,0,n,array);
        System.out.println(list.toString());
    }

    private static void getData(List<Integer[]> list,int start, int end, int[] array) {
        if(start>=end){
            Integer[] item = new Integer[array.length];
            for (int i = 0; i < array.length; i++) {
                item[i] =  array[i];
            }
            list.add(item);
        }
        for (int i = start; i < end; i++) {
            swap(i,start,array);
            getData(list,start+1,end,array);
            swap(i,start,array);
        }
    }

    private static void swap(int i, int j, int[] array) {
        int tem = array[i];
        array[i] = array[j];
        array[j] = tem;
    }
}

【三】青蛙跳

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

public class Solution {
    public   int JumpFloor(int target) {
        int count = getcount(0,target);
        return  count;
    }
    
    public  int getcount(int current,int target){
        //表示当前台阶数大于总台阶数,很显然这种情况不符合,走不通,记为 0
        if (current > target) {
            return 0;
        }
        //表示当前台阶数正好等于总的台阶数,那么这种情况符合,记为 1
        if (current == target) {
            return 1;
        }
        
        return getcount(current + 1, target) + getcount(current + 2, target);
    }
}

注意这中解法不是很适合数据比较大的,数据大导致递归深度很大,以下提供非递归的方法:
dp(i) = dp(i-2) + dp(i-1)

public class Solution {
    public int JumpFloor(int target) {
        if(target <= 2){
            return target;
        }
        int pre2 = 1, pre1 = 2;
        for (int i = 3; i <= target; i++){
            int cur = pre2 + pre1;
            pre2 = pre1;
            pre1 = cur;
        }
        return pre1;
    }
}

【四】经典问题:对于一个m*n的网格,从左上角的方格到右下角的方格,共有多少条路径(递归)

int sum(int m, int n)//递归
{
	if (m == 1 || n == 1)
		return 1;
	int total = sum(m - 1, n) + sum(m, n - 1);
	return total;
}

【五】经典问题:对于一个m*n的网格,从左上角的方格到右下角的方格的最小路径(动态规划)

public static int getMin(int[][] map, int n, int m) {
    //特殊输入
    if(map==null||n<=0||m<=0) return 0;

    //①创建动态规划结果矩阵dp[][]
    int[][] dp=new int[n][m];
    //②求解第1行第1列的结果值
    dp[0][0]=map[0][0];
    for(int i=1;i<m;i++){
        dp[0][i]=dp[0][i-1]+map[0][i];
    }
    //求第1列的结果值
    for(int i=1;i<n;i++){
        dp[i][0]=dp[i-1][0]+map[i][0];
    }
    //③从上到下,从左到右求任意dp[i][j]
    for(int i=1;i<n;i++){
        for(int j=1;j<m;j++){
            dp[i][j]=map[i][j]+Math.min(dp[i-1][j],dp[i][j-1]);
        }
    }
    //④返回右下角的结果值
    return dp[n-1][m-1];
}

【六】在反向波兰表示法中计算算术表达式的值。有效的运算符是+, - ,*,/。每个操作数可以是整数或另一个表达式

在这里插入图片描述


public static int getAns(String[] tokens){
    int returnValue = 0;
    String operators = "+-*/";

    Stack<String> stack = new Stack<String>();
    for (String t:tokens){
        if(!operators.contains(t)){
            stack.push(t);
        }
        else{
            int a = Integer.parseInt(stack.pop());
            int b = Integer.parseInt(stack.pop());
            switch (t){
                case "+":
                    stack.push(String.valueOf(a+b));
                    break;
                case "-":
                    stack.push(String.valueOf(a-b));
                    break;
                case "*":
                    stack.push(String.valueOf(a*b));
                    break;
                case "/":
                    stack.push(String.valueOf(a/b));
                    break;
            }
        }
    }
    returnValue+=Integer.parseInt(stack.pop());
    return returnValue;
}

【七】给定字符串s和单词字典dict,确定s是否可以被分割成一个或多个字典单词的空格分隔序列。

例如,给定
s =“leetcode”,
dict = [“leet”,“code”]。
返回true,因为“leetcode”可以被分段为“leet code”

public static boolean wordBreak(String s, Set<String> wordDict) {
    int[] pos = new int[s.length()+1];
    Arrays.fill(pos, -1);
    pos[0]=0;
    for(int i=0; i<s.length(); i++){
        if(pos[i]!=-1){
            for(int j=i+1; j<=s.length(); j++){
                String sub = s.substring(i, j);
                if(wordDict.contains(sub)){
                    pos[j]=i;
                }
            }
        }
    }
    return pos[s.length()]!=-1;
}

【八】给定一个只包含字符’(’,’)’,’{’,’}’,’[‘和’]'的字符串,确定输入字符串是否有效。

public static boolean isValid(String s) {
    HashMap<Character, Character> map = new HashMap<Character, Character>();
    map.put('(', ')');
    map.put('[', ']');
    map.put('{', '}');
    Stack<Character> stack = new Stack<Character>();

    for (int i = 0; i < s.length(); i++) {
        char curr = s.charAt(i);
        if (map.keySet().contains(curr)) {
            stack.push(curr);
        } else if (map.values().contains(curr)) {
            if (!stack.empty() && map.get(stack.peek()) == curr) {
                stack.pop();
            } else {
                return false;
            }
        }
    }
    return stack.empty();
}

【九】给定未排序的整数数组,找到最长连续元素序列的长度。

例如,给定[100, 4, 200, 1, 3, 2],最长的连续元素序列应该是[1, 2, 3, 4]。它的长度是4

public int longestConsecutive(int[] nums) {
    HashSet<Integer> set = new HashSet<>();
    for(int num: nums) set.add(num);
    int result = 0;

    for(int num: nums){
        int count = 1;

        int down = num-1;
        while(set.contains(down)){
            set.remove(down);
            down--;
            count++;
        }

        int up = num+1;
        while(set.contains(up)){
            set.remove(up);
            up++;
            count++;
        }
        result = Math.max(result, count);
    }
    return result;
}

【十】给定mxn元素矩阵(m行,n列),以螺旋顺序返回矩阵的所有元素。

 public static List<Integer> getMria(int[][]array){
        List<Integer> list = new ArrayList<>();

        int left = 0;
        int right=array[0].length-1;
        int top = 0;
        int bottom = array.length-1;

        while (list.size()<((right+1)*(bottom+1))){

            for (int i = left; i <= right; i++) {
                list.add(array[top][i]);
            }
            top++;

            for (int i = top; i <=bottom ; i++) {
                list.add(array[i][right]);
            }
            right--;

            if(top>bottom)
                break;
            for (int i = right; i >=left ; i--) {
                list.add(array[bottom][i]);
            }
            bottom--;

            if(left>right)
                break;
            for (int i = bottom; i >=top; i--) {
                list.add(array[i][left]);
            }
        }
        return list;
    }

【十一】给定一个链表,确定它是否有一个循环,如果我们有2个指针 - 快速和慢速。如果存在圆圈,则保证快速的一个将遇到慢速的一个。

public static boolean hasCycle(ListNode head) {
    ListNode fast = head;
    ListNode slow = head;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;

        if (slow == fast)
            return true;
    }
    return false;
}

【十二】输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
     public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        //由于重建二叉树的过程会用到很多边界值,所以题目所给的方法的参数是不够用的
        //所以,在下面重载了这个方法,每次传入前序和中序序列以及起始位置
        TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
        return root;
    }
    private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {
        //这里是判断结束的标志,由于是递归算法,我们不可能一直执行下去,所以需要结束标志
        //下面这两种情况发生一个就会结束
        if(startPre>endPre||startIn>endIn)
        {
            return null;
        }
        //首先找到根节点
        TreeNode root=new TreeNode(pre[startPre]);
        //对中序遍历进行查找根节点
        for(int i=startIn;i<=endIn;i++)
        {
            //找到之后,分别对左子树和右子树进行递归算法,重复此步骤
            if(in[i]==pre[startPre])
            {
                //重建二叉树的关键就是找到其中的边界值,边界值在图中已经做了描述
                root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
                root.right=reConstructBinaryTree(pre,startPre+i-startIn+1,endPre,in,i+1,endIn);
                break;
            }
        }
        return root;
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值