手写算法代码,你准备好了吗

常见面试算法题汇总    剑指offer(在线编程)  剑指offer(案例总结)

1、单例

 饿汉式是类一加载进内存就创建好了对象;

//饿汉式 
class Singleton {  
    private Singleton() {} 
    private static Singleton s = new Singleton(); 
    public static Singleton getInstance() {  
         return s; 
        } 
      }  


懒汉式是类加载进内存的时候,对象还没有存在,要使用该对象的时候再new出来,*懒汉式是延迟加载,如果多个线程同时操作懒汉式时就有可能出现线程安全问题 为解决饱汉式的线程安全问题,解决线程安全问题可以加同步来解决。但是加了同步之后,每一次都要比较锁,效率就变慢了。

//懒汉式 
class Single { 
    private Single() {} 
    private static Single s = null ;  
    public static Single getInstance() { 
    public static synchronized Single getInstance() {    //加锁同步安全
        if (s == null) {  
          s = new Single();    
        }         
      return s;   
} }  


通过双重判断来提高程序效率,所谓“双重检查加锁”机制,指的是

//双重检查
class Single { 
    private Single() {} 
    private volatile static Single s = null;  
    public static Single getInstance() {
       //先检查实例是否存在,如果不存在才进入下面的同步块
        if (s == null) {  
            //同步快,线程安全创建实例
           synchronized (Singleton.class) {
             //再次检查实例是否存在,如果不存在才真正的创建实例
                if(s == null){
                     s = new Single();    
                }
              }
        }         
      return s;   
} }

1、第一个条件是说,如果实例创建了,那就不需要同步了,直接返回就好了。  if (singleton== null)  {
2、不然,我们就开始同步线程。                               synchronized (Singleton.class) {
3、第二个条件是说,如果被同步的线程中有一个线程创建了对象,那么别的线程就不用再创建了。  if (singleton== null)  {

问题主要在于singleton = new Singleton()这句,这并非是一个原子操作,事实上在 JVM 中这句话大概做了下面 3 件事情
1、给 singleton 分配内存
2、调用 Singleton 的构造函数来初始化成员变量,形成实例
3、将singleton对象指向分配的内存空间(执行完这步 singleton才是非 null 了)

但是在 JVM 的即时编译器中存在指令重排序的优化。也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2。如果是后者,则在 3 执行完毕、2 未执行之前,被线程二抢占了,这时 instance 已经是非 null 了(但却没有初始化),所以线程二会直接返回 instance,然后使用,然后顺理成章地报错

对此,我们只需要把singleton声明成 volatile 就可以了,有两个功用:

1)这个变量不会在多个线程中存在复本,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量

2)这个关键字会禁止指令重排序优化。也就是说,在 volatile 变量的赋值操作后面会有一个内存屏障(生成的汇编代码上),读操作不会被重排序到内存屏障之前。

静态内部类:

支持多线程-懒汉式
//特点:利用静态内部类(只有在出现它的引用时才被加载),完成懒加载

class Single{
    private Single(){}
    public static Single getInstance(){
        return SingleHolder.instance;
    }
    private static class SingleHolder{
        public static Single instance = new Single();
    }
}



2、回文
“回文串”是一个正读和反读都一样的字符串,如“level”或者“noon”等就是回文串。

第一种
        String str = "1234321";
        StringBuilder sb = new StringBuilder(str);
        String newStr = sb.reverse().toString(); 
        if(newStr.equals(str)){
            System.out.println(str+"是回文字符串");
        }else {
            System.out.println(str+"不是是回文字符串");
        }
第二种
        String str = "1234321";
        int count = 0;
        for (int i = 0; i < str.length() / 2; i++) {
            if ((str.substring(i, i + 1)).equals(str.substring(str.length() - 1- i, str.length() - i))) {
                count++;
            }
        }
        if (count == str.length() / 2) {
            System.out.println("是回文字符串");
        }else{
            System.out.println("不是回文字符串");
        }
第三种 
public static boolean palindromeNumber(int num) {
        int div = 1;
        while(num / div >= 10){
            div *= 10;
        }
        while(num > 0){
            if(num / div != num % 10){
                return false;
            }
            num = (num % div) / 10;
            div /= 100;
        }
        return true;
    }


3、翻转字符串
翻转单词顺序列,如输入“student. a am I”,输出“I am a student.”

      String str ="student a am I";
       if(str.trim().equals("") || str == null){
            return str;
        }
        String [] c = str.split(" ");
        StringBuffer sb = new StringBuffer();
        for(int i = c.length;i>0;i--){
          sb.append(c[i-1]);
           if(i>1){
               sb.append(" ");
           }
        }
        return sb.toString();

翻转一个整数  例如 22334455

public static int reverseInteger(int n) {
        int num = 0;
        while (n != 0) {
            int temp = num * 10 + n % 10;
            n = n / 10;
            if (temp / 10 != num) {
                num = 0;
                break;
            }
            num = temp;
        }
        return num;
    }


4、线程
(1)用三个线程,顺序打印字母A-Z,输出结果是1A、2B、3C、1D 2E...

    static char c = 'A';
    static int i = 0;
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            public void run() {
                synchronized (this) {//加锁
                    try {
                        int threadId = Integer.parseInt(Thread.currentThread().getName());
                        while (i < 26) {
                            if (i % 3 == threadId - 1) {
                                System.out.println(threadId +" "+ (char) c++);
                                i++;
                                notifyAll();// 唤醒处于等待状态的线程
                            } else {
                                wait();// 释放当前锁并进入等待状态
                            }
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }//执行结束释放当前锁
            }
        };
        Thread t1 = new Thread(runnable, "1");
        Thread t2 = new Thread(runnable, "2");
        Thread t3 = new Thread(runnable, "3");
        t1.start();
        t2.start();
        t3.start();
    }

(2)多线程以及锁机制
创建2个线程共享10张票,在while()循环中添加sleep()方法,由于线程有延迟,出现了票数为负数的情况,此时需要同步锁机制,使用synchronized同步代码块,共享资源的代码只能有一个线程访问。

public static void main(String [] args){
        Ticket ticket = new Ticket();
        new Thread(ticket,"1").start();
        new Thread(ticket,"2").start();
    }

     static class Ticket implements Runnable{
        private int tickets = 10;
        //锁对象是任意类型,唯一的。不能放到run方法中,否则每次创建一个新对象有不同的锁,无法同步。
        Object lock = new Object();
        public void run() {
            while (true){
                synchronized (lock){  //同步代码块
                    if(tickets>0){
                        try {
                            Thread.sleep(10); //休眠10秒
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(tickets--);
                    }else {
                        break;  //跳出循环,终止程序
                    }
                }
            }
        }
    }

(3)、死锁
创建了china线程和Ameri线程,china线程中拥有chop锁,只有获得knife锁才能执行完毕,而Ameri线程中拥有knife锁,只有获得chop锁才能执行完毕,两个线程需要对方所占用的锁,但是无法释放自己拥有的锁,全都处于挂起状态。

public class DeadLockThread {
    public static void main(String [] args){
        new Thread(new DeadLock(true),"china").start();;
        new Thread(new DeadLock(false),"Ameri").start();
    }
}

 class DeadLock implements Runnable{
    //定义chop和knife两种锁对象
    Object chop = new  Object();
    Object knife = new  Object();
    boolean flag;
    public DeadLock(boolean flag) {
        this.flag = flag;
    }
    @Override
    public void run() {
        if(flag){
            while (true){
             synchronized (chop){
                 System.out.println(Thread.currentThread().getName()+"----chop");
                 synchronized (knife){
                     System.out.println(Thread.currentThread().getName()+"----knife");
                 }
              }
            }
        }else {
            while (true){
                synchronized (knife){
                    System.out.println(Thread.currentThread().getName()+"----knife");
                    synchronized (chop){
                        System.out.println(Thread.currentThread().getName()+"----chop");
                    }
                }
            }
        }
    }
}


5、斐波拉契数列介绍
斐波那契数列(Fibonacci sequence),又称黄金分割数列。斐波那契数列源自于兔子繁殖问题,是数学家列昂纳多·斐波那契引入的,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……
数列中的每1项称为“斐波那契数”,斐波那契数的前两项都是1,从第3项开始,每1项都等于前2项之和。
a[n]=a[n-1]+a[n-2]

1、利用循环的方式
        //声明三个变量
        int a=1,b=1,c=0;
        // 从第三项开始,每个数字都都等于前面两个数字之和
        for (int i = 3; i <=10 ; i++) {
            c=a+b;
            a= b;
            b=c;
            System.out.println(c);
        }

2、利用递归的方式
    public static int computer(int num){
        if(num == 1 || num ==2){
            return 1;
        }
        return computer(num-1)+computer(num-2);
    }

6、递归和循环的比较:
1、递归慢的原因:

  递归的实现是通过调用函数本身,函数调用的时候,每次调用时要做地址保存,参数传递等,这是通过一个递归工作栈实现的。具体是每次调用函数本身要保存的内容包括:局部变量、形参、调用函数地址、返回值。那么,如果递归调用N次,就要分配N*局部变量、N*形参、N*调用函数地址、N*返回值。
2、用循环效率会比递归效率高吗?
并不是说循环效率就一定比递归高,递归和循环是两码事,递归带有栈操作,循环则不一定
递归优点:代码简洁、清晰,并且容易验证正确性
       缺点:运行需要多次数函数调用,如果调用层数比较深,需要增加额外的堆栈处理(还有可能出现堆栈溢出的情况),比如参数传递需要压栈等操作,会对执行效率有一定影响。

循环优点:速度快,结构简单
       缺点:并不能解决所有的问题。有的问题适合使用递归而不是循环。如果使用循环并不困难的话,最好使用循环

7、二叉树

class TreeMode{
        public TreeMode left,right;
        public int val;

        public TreeMode(int val){
            this.val = val;
        }
    }

    //先序  根左右
    public void preTraverse(TreeMode root){
        if(root != null){
            System.out.println(root.val);
            preTraverse(root.left);
            preTraverse(root.right);
        }
    }

    //中序  左根右
    public void inTraverse(TreeMode root){
        if(root !=null){
            inTraverse(root.left);
            System.out.println(root.val);
            inTraverse(root.right);
        }
    }

    //后续  左右根
    public void postTraverse(TreeMode root){
        if(root !=null){
            postTraverse(root.left);
            postTraverse(root.right);
            System.out.println(root.val);
        }
    }

    //左右翻转
    public void invert(TreeMode root){
       TreeMode temp = root.left;
       root.left = root.right;
       root.right = temp;

       invert(root.left);
       invert(root.right);
    }

    //最大值
    public int getMax(TreeMode root){
        if(root == null){
            return Integer.MIN_VALUE;
        }else {
            int left = getMax(root.left);
            int right = getMax(root.right);
            return Math.max(Math.max(left,right),root.val);
        }
    }

    //最大深度
    public int maxDepth(TreeMode root){
        if(root == null){
            return 0;
        }
        int left = maxDepth(root.left);
        int right = maxDepth(root.right);
        return Math.max(left,right)+1;
    }

    //最小深度
    public int minDepth(TreeMode root){
        if(root == null){
            return 0;
        }
        int left = minDepth(root.left);
        int right = minDepth(root.right);
        if(left == 0){
            return right+1;
        }else if(right == 0){
            return left+1;
        }else {
            return Math.min(left,right)+1;
        }
    }

8、链表

public class ListNode {
     int val;
     ListNode next ;
     ListNode(int x) {
         val = x;  
         next = null;
    }
}



删除节点
public void deleteNode(ListNode node) {
    if (node.next == null){
        node = null;
        return;
    }
    // 取缔下一节点
    node.val = node.next.val
    node.next = node.next.next
}




翻转链表
 方法二: 递归,使链表从尾节点开始指向前一个节点
public ListNode reverseLinkedList(ListNode head){
    if (head == null || head.next == null){
        return head;
    }
    ListNode pNode = reverseLinkedList(head.next);
    head.next.next = head;
    head.next = null;
    return pNode;
}




判断链表是否有环
public static boolean containCircle(Node head) {
        Node fastPoint = head;
        Node slowPoint = head;
        if (fastPoint == null) {
            return false;
        }
        while (fastPoint.next != null) {
            fastPoint = fastPoint.next.next;
            slowPoint = slowPoint.next;
            if (fastPoint == slowPoint) {
                return true;
            }
        }
        return false;
    }



    /**
     * 判断链表是否为回文链表
     */
    public static boolean isPalindrome(Node head) {
        if (head == null || head.next == null) {
            return true;
        }
        Node quick = head;
        Node slow = head;
        //快慢指针,快指针一次走两步,慢指针一次走一步
        while (quick != null && quick.next != null) {
            quick = quick.next.next;
            slow = slow.next;
        }
        //从slow开始反转后半段链表
        Node pre = null;
        while (slow != null) {
            Node temp = slow.next;
            slow.next = pre;
            pre = slow;
            slow = temp;
        }
        //对比前半段和后半段的data值是否相同
        while (pre != null) {
            if (pre.val == head.val) {
                pre = pre.next;
                head = head.next;
            } else {
                return false;
            }
        }
        //返回true
        return true;
    }




//链表每k个节点一组进行翻转,如果节点总数不是k的整数倍保持原有顺序。

    public ListNode reversekGroup(ListNode head,int k){
        if(head == null || head.next == null || k==1){
            return head;
        }
        //寻找第k个节点
        ListNode kNode = head;
        for (int i = 0; i < k && kNode!= null; i++) {
            kNode = head.next;
        }

        //若不够k个节点不用翻转直接返回head
        if(kNode == null){
            return head;
        }
        //若够k个节点,则翻转前k个节点,把k+1个节点记录下来
        kNode = kNode.next;
        head.next = reversekGroup(kNode,k);
        ListNode pNode = reverse(head,k);
        return pNode;
    }

     ListNode reverse(ListNode head, int k) {
        ListNode pNode = reverse(head.next,k-1);
        head.next.next = head;
        head.next = null;
        return pNode;
    }



//链表每k个节点一组进行翻转,如果节点总数不是k的整数倍,剩余的直接翻转

    public ListNode reversekGroup(ListNode head,int k){
        if(head == null || head.next == null || k==1){
            return head;
        }
        //寻找第k个节点
        ListNode kNode = head;
        for (int i = 0; i < k && kNode!= null; i++) {
            kNode = head.next;
        }
        
        //链表每k个节点一组进行翻转,如果节点总数不是k的整数倍,剩余的直接翻转。
        kNode = kNode.next;
        if(kNode == null){
            head.next = null;
        }else {
            head.next = reversekGroup(kNode,k);
        }
        ListNode pNode = reverse(head,k);
        return pNode;
    }

     ListNode reverse(ListNode head, int k) {
        ListNode pNode = reverse(head.next,k-1);
        head.next.next = head;
        head.next = null;
        return pNode;
    }

9、栈和队列
用两个栈实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型

  • 入队:将元素进栈A
  • 出队:判断栈B是否为空,如果为空,则将栈A中所有元素pop,并push进栈B,栈B出栈, 反之栈B直接出栈

public class Solution{
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    //入队
    public void add(int node){
        stack1.push(node);
    }
    //出队
    public int poll(){
        if (stack1.empty(0 && stack2.empty())){
            throw new RuntimeException("Queue is empty!");
        }
        if (stack2.empty()){
            while (!stack1.empty()){
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }
}

10、二分搜索
了解哪些查找算法,时间复杂度都是多少?

//递归的方式实现--二分查找
public int binarySearch(int[] arr, int start, end, int hkey){
   
    int mid = start + (end - start) / 2;    //防止溢位
    if (arr[mid] > hkey) {
        return binarySearch(arr, start, mid - 1, hkey);
    }
    if (arr[mid] < hkey) {
        return binarySearch(arr, mid + 1, end, hkey);
    } 
    return mid;  
}

//循环的方式实现
private static int binarySearch(int[] array, int hkey) {
        int left = 0;
        int right = array.length - 1;
        int mid = (left + right) / 2;
            if (hkey < array[mid]) {
                right = mid - 1; 
            } else if (aim > array[mid]) {
                left = mid + 1;  
            } else {
                return mid;
            }
    }

11、数组

删除元素  


删除排序数组中的重复数字

   在原数组中“删除”重复出现的数字,使得每个元素只出现一次,并且返回“新”数组的长度,新的数组

(第1种方法)
public class removeElem {
    public static void main(String[] args){
        Object[] arr = {"a","b","b","c","d"};

        Object[] objects = ifRepeat(arr);
        System.out.println(objects.length);
        System.out.println(objects);
    }

   //list.contains()
    public static Object[]  ifRepeat(Object[] arr){
        List list = new ArrayList();
        for(int i=0;i<arr.length;i++){
            if(!list.contains(arr[i])){
                list.add(arr[i]);
            }
        }
        Object[] newArr = list.toArray();
        return newArr;
    }

    //HashSet()
    public static Object[] ifRepeat1(Object[] arr){
        Set set = new HashSet();
        for (int i = 0; i < arr.length; i++) {
            set.add(arr[i]);
        }
        return set.toArray();
    }
}



(第2种方法)
public int removeDuplicates(int[] A) {
    if (A == null || A.length == 0) {
        return 0;
    }
    
    int size = 0;
    for (int i = 0; i < A.length; i++) {
        if (A[i] != A[size]) {
            A[++size] = A[i];
        }
    }
    return size + 1;
}



合并排序数组

   合并两个排序的整数数组A和B变成一个新的数组。可以假设A具有足够的空间去添加B中的元素。
public void mergeSortedArray(int[] A, int m, int[] B, int n) {
    int i = m - 1, j = n - 1, index = m + n - 1;
    while (i >= 0 && j >= 0) {
        if (A[i] > B[j]) {
            A[index--] = A[i--];
        } else {
            A[index--] = B[j--];
        }
    }
    while (i >= 0) {
        A[index--] = A[i--];
    }
    while (j >= 0) {
        A[index--] = B[j--];
    }
}


12、排序     十大经典排序算法详细总结(含JAVA代码实现)
(1)冒泡排序

 public static int[] bubbleSort(int[] array) {
      if (array.length == 0){
           return array;
         }
      for (int i = 0; i < array.length; i++){ 
         //如果未发生交换,则说明数组已经有序,不必再排序了
          boolean isSwap = true;
          for (int j = 0; j < array.length - 1 - i; j++){
            if (array[j + 1] < array[j]) {
                  int temp = array[j + 1];
                  array[j + 1] = array[j];
                  array[j] = temp;
                  isSwap = false
              }
           }         
         if(isSwap){
           break;
           }   
      }
      return array;
  }

(2)选择排序

public static int[] selectionSort(int[] array) {
         if (array.length == 0){
           return array;
         }
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            for (int j = i; j < array.length; j++) {
                if (array[j] < array[minIndex]) //找到最小的数
                    minIndex = j; //将最小数的索引保存
            }
            int temp = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp;
        }
        return array;
    }

(3)插入排序

public static int[] insertionSort(int[] array) {
        if (array.length == 0){
           return array;
         }
        int current;
        for (int i = 0; i < array.length - 1; i++) {
            current = array[i + 1];
            int preIndex = i;
            while (preIndex >= 0 && current < array[preIndex]) {
                array[preIndex + 1] = array[preIndex];
                preIndex--;
            }
            array[preIndex + 1] = current;
        }
        return array;
    }

(4)快速排序
      快速排序其实是冒泡排序的升级版,同样的基于两两交换,但是引入了分治的思想。通过使用中线,对需要排序的区间进行了重新的一个划分,而这内部剩下的性能还有一方面就是在于这个中线,因为数值的比较不再是全局,而是局部,从效率计算上来讲一般情况可降到O(nlogn),当然极端情况就可能退化回我们的冒泡排序。

public static void main(String [] args){
        int [] arr = {1,4,6,3,7,0,2};
        int[] quickSort = QuickSort(arr, 0, arr.length-1);
        System.out.println(quickSort);
    }

    public static int[] QuickSort(int[] array, int start, int end) {
    if (array.length < 1 || start < 0 || end >= array.length || start > end) return null;
        int smallIndex = partition(array, start, end);
        if (smallIndex > start)
            QuickSort(array, start, smallIndex - 1);
        if (smallIndex < end)
            QuickSort(array, smallIndex + 1, end);
        return array;
    }

    public static int partition(int[] array, int start, int end) {
        int pivot = (int) (start + Math.random() * (end - start + 1));
        int smallIndex = start - 1;
        swap(array, pivot, end);
        for (int i = start; i <= end; i++)
            if (array[i] <= array[end]) {
                smallIndex++;
                if (i > smallIndex)
                    swap(array, i, smallIndex);
            }
        return smallIndex;
    }

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

13、数组中重复的数字
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

public class Solution {
    public boolean duplicate(int numbers[],int length,int [] duplication) {
       StringBuffer sb = new StringBuffer();
        for(int i=0;i<length;i++){
            sb.append(numbers[i]+"");
        }
        for(int j=0;j<length;j++){
            if(sb.indexOf(numbers[j]+"") != sb.lastIndexOf(numbers[j]+"")){
                duplication[0] = numbers[j];
                return true;
            }
        }
        return false;
     }
  }

14、把字符串转换成整数
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

public class Solution {
    public static int StrToInt(String str) {
        if(str.equals("") || str.length() == 0 || str.equals("+") || str.equals("-")){
            return 0;
        }
        char [] newstr =  str.toCharArray();
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<newstr.length;i++){
            if(0 < newstr[i] &&  newstr[i]< 97){
                sb.append(newstr[i]);
            }else{
                return 0;
            }
        }
        return Integer.parseInt(sb.toString().replace("+",""));
    }
}

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

public class Solution {
    public int JumpFloor(int target) {
       if(target<4){
           return target;
       }
        return JumpFloor(target-1)+JumpFloor(target-2);
    }
}

 变态跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

public class Solution {
    public int JumpFloorII(int target) {
        if(target<0){
           return target;
       }
        return (int) Math.pow(2, target - 1);
    }
}

16、替换空格
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

public class Solution {
    public String replaceSpace(StringBuffer str) {
        if(str == null){
            return str.toString();
        }
        String newstr = str.toString().replaceAll(" ","%20");
        return newstr;
    }
}

17、左旋转字符串
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!

public class Solution {
    public String LeftRotateString(String str,int n){
        if(str.length()==0 || n<0 ){
            return "";
        }
        return str.substring(n,str.length())+str.substring(0,n);
    }
}

18、爬楼梯
假设你正在爬楼梯,需要n步你才能到达顶部。但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部?

public int climbStairs(int n) {
    if (n == 0) return 0;
    int[] array = new int[n + 1];
    array[0] = 1;
    if (array.length > 1) {
        array[1] = 1;
    }
    
    for(int i = 2; i < array.length; i++) {
        array[i] = array[i - 1] + array[i - 2];
    }
    return array[n];
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值