剑指offer算法题:输出旋转数组中的最小值。

package algorithm;

/**
 * author : fzy
 * date   : 2019/11/12 8:26
 * desc   : 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
 * 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
 * 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
 */
public class demo6 {
  public static void main(String[] args) {
    int [] array = {6,7,8,9,3,4};
    System.out.println(findMin1(array));
    System.out.println(findMin2(array));
  }
 
  //方法一
  public static int findMin1(int[] array){
    int i = 0;
    while (array[i]<array[i+1]){
      i++;
    }
    return array[i+1];
  }

 //方法二
  public static int findMin2(int[]array){
    int low = 0;
    int high = array.length - 1;
    int middle = 0;
    while (array[low]>array[high]){
      //只有两个数时,最右侧为最小值
      if(high - low == 1){
        middle = high;
        break;
      }
      middle = (low+high)/2;
      if(array[middle]>=array[low]){
        low = middle;
      }else if(array[middle]<=array[high]){
        high = middle;
      }
    }
    return array[middle];
  }
}

题目:输出斐波那契数列第n项:

/**
 * author : fzy
 * date   : 2019/11/14 8:23
 * 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。n<=39
 * 0 1 1 2 3 5 8 13.....
 * n>2时,fn = fn-1 + fn-2
 */
public class demo7 {
  public static void main(String[] args) {
     int n = 7;
     System.out.println(fibonacci(n));
  }
  public static int fibonacci(int n){
    if(n==0){
      return 0;
    }else if(n==1){
      return 1;
    }else{
      int zero = 0;
      int one = 1;
      int fN = 0;
      for(int i=2;i<=n;i++){
        fN = one + zero;
        zero = one;
        one = fN;
      }
      return fN;
    }
  }

}

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

package algorithm;

/**
 * author : fzy
 * date   : 2019/11/15 8:29
 * 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
 */
public class demo8 {

  public static void main(String[] args) {
     System.out.println(JumpFloor1(15));
     System.out.println(JumpFloor2(15));
  }
  //第n阶等于n-1阶和n-2阶的和
  public static int JumpFloor1(int n){
    if(n<1)
      return 0;
    if(n==1)
      return 1;
    if(n==2)
      return 2;
    return JumpFloor1(n-1)+JumpFloor1(n-2);
  }
  //斐波那契数列解法
  public static int JumpFloor2(int n){
    if(n==1){
      return 1;
    }
    if(n==2){
      return 2;
    }
    int one = 1;
    int two = 2;
    int count = 0;
    for(int i=3;i<=n;i++){
      count = one + two;
      one = two;
      two = count;
    }
    return count;
  }
}

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

package algorithm;

/**
 * author : fzy
 * date   : 2019/11/16 8:27
 * 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。
 * 求该青蛙跳上一个n级的台阶总共有多少种跳法。
 */
public class demo9 {
  public static void main(String[] args) {
    System.out.println(jumpFloor2(10));
    System.out.println(jumpFloorII(10));
  }

  //发现规律,计算2的(n-1)次方
  public static int jumpFloor2(int n) {
     int fn = 1;
     for(int i=1;i<n;i++){
       fn = fn * 2;
     }
     return fn;
  }

  //每一阶等于前面一阶的方法数加一,采用动态规划
  public static int jumpFloorIII(int n){
     int first = 1;
     int sum = 1;
     while (n > 1){
       sum += first;
       first = sum;
       n -- ;
     }
     return sum;
  }
}

题目:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?(本质还是斐波那契数列,可用递归或动态规划解决,同上面

题目:反转链表,并且输出反转后的链表

package algorithm;
import bean.ListNode;

/**
 * author : fzy
 * date   : 2019/11/20 8:33
 * desc  : 反转链表,并输出反转后的链表
 */
public class demo11 {
  public static void main(String[] args) {
    ListNode head = new ListNode(1);
    ListNode node1 = new ListNode(2);
    ListNode node2 = new ListNode(3);
    ListNode node3 = new ListNode(4);
    ListNode end = new ListNode(5);
    head.setNext(node1);
    node1.setNext(node2);
    node2.setNext(node3);
    node3.setNext(end);

    //System.out.println(reverseNode(head).getValue());
    ListNode node = reverseNode(head);
    while (node!=null){
      System.out.println("node is:"+node.getValue());
      node = node.getNext();
    }
  }
  public static ListNode reverseNode(ListNode head){
    ListNode reverseNode = null;//反转后的头结点
    ListNode currentHead = head;
    ListNode previoursNode = null;
    while (currentHead!=null){
      ListNode nextNode = currentHead.getNext();
      if(nextNode==null){
        reverseNode = currentHead;
      }
        currentHead.setNext(previoursNode);
        previoursNode = currentHead;
        currentHead = nextNode;
    }
    return reverseNode;
  }
}

package bean;

/**
 * author : fzy
 * date   : 2019/11/8 8:29
 */
public class ListNode {
  private int value;
  private ListNode next;

  public ListNode(int value) {
    this.value = value;
  }

  public ListNode(int value, ListNode next) {
    this.value = value;
    this.next = next;
  }

  public int getValue() {
    return value;
  }

  public void setValue(int value) {
    this.value = value;
  }

  public ListNode getNext() {
    return next;
  }

  public void setNext(ListNode next) {
    this.next = next;
  }
}

题目:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。(合并链表)

package algorithm;

import bean.ListNode;

/**
 * author : fzy
 * date   : 2019/11/21 8:53
 * desc   : 合并链表
 */
public class demo12 {
  public static void main(String[] args) {
    ListNode head1 = new ListNode(1);
    ListNode node3 = new ListNode(2);
    ListNode node5 = new ListNode(3);
    ListNode node7 = new ListNode(7);
    head1.setNext(node3);
    node3.setNext(node5);
    node5.setNext(node7);

    ListNode head2 = new ListNode(4);
    ListNode node4 = new ListNode(5);
    ListNode node6 = new ListNode(6);
    ListNode node8 = new ListNode(8);
    head2.setNext(node4);
    node4.setNext(node6);
    node6.setNext(node8);

    ListNode result = combineList(head1,head2);
    while (result!=null){
      System.out.println(result.getValue());
      result = result.getNext();
    }
  }

  //方法一:递归
  public static ListNode combineList(ListNode head1,ListNode head2){
    if(head1==null){
      return head2;
    }else if(head2==null){
      return head1;
    }
    ListNode listAll = null;
    if(head1.getValue()<head2.getValue()){
      listAll = head1;
      listAll.setNext(combineList(head1.getNext(),head2));
    }else{
      listAll = head2;
      listAll.setNext(combineList(head1,head2.getNext()));
    }
    return listAll;
  }

  //方法二:非递归
  public static ListNode mergeList(ListNode head1,ListNode head2){
    ListNode result = null;
    ListNode currentNode = null;
    while (head1!=null&&head2!=null){
      if(head1.getValue()<head2.getValue()){
        if(result==null){
          result = head1;
        }else{
          currentNode.setNext(head1);
        }
        currentNode = head1;
        head1 = head1.getNext();
      }else{
        if(result==null){
          result.setNext(head2);
        }else{
          currentNode.setNext(head2);
        }
        currentNode = head2;
        head2 = head2.getNext();
      }
    }
    if(head1==null&&head2!=null){
      currentNode.setNext(head2);
    }
    if(head2==null&&head1!=null){
      currentNode.setNext(head1);
    }
    return result;
  }

}

题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

package algorithm;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * author : fzy
 * date   : 2019/11/26 8:30
 */
public class demo13 {
  public static void main(String[] args) {
    List<Integer>list1 = new ArrayList<>();
    list1.add(1);
    list1.add(3);
    list1.add(2);
    list1.add(4);
    list1.add(5);
    List<Integer>list2 = new ArrayList<>();
    list2.add(5);
    list2.add(4);
    list2.add(3);
    list2.add(2);
    list2.add(1);
     System.out.println(isPopOrder(list1,list2));

     Stack<Integer>stack1 = new Stack<>();
     stack1.push(1);
     stack1.push(2);
     stack1.push(4);
     stack1.push(3);
     stack1.push(5);
    Stack<Integer>stack2 = new Stack<>();
    stack2.push(5);
    stack2.push(3);
    stack2.push(4);
    stack2.push(2);
    stack2.push(1);
    System.out.println(isPopOrder2(stack1,stack2));

    int[]array1 = {1,2,3,4,5};
    int[]array2 = {5,4,3,2,1};
    System.out.println(IsPopOrder(array1,array2));
  }
  public static boolean isPopOrder(List<Integer> list, List<Integer>pop){
    Stack<Integer>push = new Stack<>();
    for(int i=0;i<list.size();i++){
      push.push(list.get(i));
    }
    int i = 0;
    while (!push.empty()){
     if(push.pop()!=pop.get(i)){
       return false;
     }else {
       i++;
     }
    }
    return true;
  }

  public static boolean isPopOrder2(Stack<Integer>stack1,Stack<Integer>stack2){
    Stack<Integer>copy = new Stack<>();
    while (!stack1.empty()){
      copy.push(stack1.pop());
    }
    while (!copy.empty()){
      if(copy.pop()!=stack2.pop()){
        return false;
      }
    }
    return true;
  }

  public static boolean IsPopOrder(int [] pushA,int [] popA) {
    Stack<Integer> assistant = new Stack<Integer>();
    int index = 0;//用于标识弹出序列位置
    for(int i=0; i < pushA.length;i++)
    {
      assistant.push(pushA[i]);
      //如果栈不为空,且栈顶元素等于弹出序列
      while(!assistant.isEmpty() && assistant.peek() == popA[index])
      {
        assistant.pop();
        index += 1;//弹出序列后移
      }
    }

    return assistant.isEmpty();
  }
}

题目:统计一个数字在排序数组中出现的次数。

package algorithm;

/**
 * author : fzy
 * date   : 2019/11/27 8:47
 * 统计一个数字在排序数组中出现的次数。
 */
public class demo14 {

  public static void main(String[] args) {
    int[]array = {1,2,3,4,4};
    System.out.println(solution1(array,2));
  }
  public static int solution1(int[]array,int k){
    int num = 0;
    for(int i=0;i<array.length;i++){
      if(array[i]==k){
        num++;
      }else{
        if(num!=0){
          break;
        }
      }
    }
    return num;
  }

  
    public static int GetNumberOfK(int [] array , int k) {
        if (array == null || array.length == 0) return 0;
        HashMap<Integer, Integer> map = new HashMap<>();
        int result = 0;
        for(int i=0;i<array.length;i++) {
            int a = array[i];
            if (map.containsKey(a)) {
                map.put(a, map.get(a) + 1);
            }else{
                map.put(a, 1);
            }
        }
        if (map.get(k) != null) {
            result = map.get(k);
        }
        return result;
    }

    

}

题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

package algorithm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * author : fzy
 * date   : 2019/11/28 8:22
 * desc   : 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
 */
public class demo15 {
  public static void main(String[] args) {
     int[]array = {2,4,3,6,3,2,5,5};
     int[]num1 = new int[1];
     int[]num2 = new int[2];
     FindNumsAppearOnce(array,num1,num2);
     System.out.println(num1[0]);
     System.out.println(num2[0]);
  }
  public static void FindNumsAppearOnce(int[]array,int [] num1,int[]num2){
    Map<Integer,Integer> map = new HashMap<>();
    for(int i=0;i<array.length;i++){
      if(map.containsKey(array[i])){
        int value = map.get(array[i]);
        map.put(array[i],value+1);
      }else{
        map.put(array[i],1);
      }
    }
    int index = 0;
    for(int i=0;i<array.length;i++){
      if(map.get(array[i])==1){
        if(index==0){
          num1[0] = array[i];
          index++;
        }else{
          num2[0] = array[i];
          break;
        }
      }
    }
  }

  public static void FindNumsAppearOnce2(int[]array,int [] num1,int[]num2){
    List<Integer>listA = new ArrayList<>();
    List<Integer>listB = new ArrayList<>();
    for(int i=0;i<array.length;i++){
      Integer value = array[i];
      if(!listA.contains(value)&&!listB.contains(value)){
        listA.add(value);
      }else{
        listA.remove(value);
        listB.add(value);
      }
    }
    num1[0]=listA.get(0);
    num2[0]=listA.get(1);
  }
}

题目:输入两个链表,找出它们的第一个公共结点。

package algorithm;

import bean.ListNode;
/**
 * author : fzy
 * date   : 2019/11/29 8:34
 * desc   : 输入两个链表,找出它们的第一个公共结点。
 * 首先要理解什么是公共节点,并不是两个节点的值相同就是公共节点。
 * 而是在第一链表和第二链表中都存在一个节点,该节点往后的子链表在两个链表中是相同的。
 */
public class demo16 {
  public static void main(String[] args) {
    ListNode head = new ListNode(1);
    ListNode node2 = new ListNode(2);
    ListNode node3 = new ListNode(3);
    ListNode node4 = new ListNode(4);
    ListNode node5 = new ListNode(5);
    ListNode node6 = new ListNode(6);
    ListNode head2 = new ListNode(10);
    ListNode node7 = new ListNode(9);
    head2.setNext(node7);
    node7.setNext(head);
    head.setNext(node2);
    node2.setNext(node3);
    node3.setNext(node4);
    node4.setNext(node5);
    node5.setNext(node6);
    System.out.println(getListNodeLength(head2));
  }
  public static ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
     int length1 = getListNodeLength(pHead1);
     int length2 = getListNodeLength(pHead2);
     int diff = 0;
     ListNode longNode;
     ListNode shortNode;
     if(length1>length2){
       diff = length1 - length2;
       longNode = pHead1;
       shortNode = pHead2;
     }else{
       diff = length2 - length1;
       longNode = pHead2;
       shortNode = pHead1;
     }
     while (diff!=0){
       longNode = longNode.getNext();
       diff--;
     }
     while (longNode!=null&&shortNode!=null&&longNode!=shortNode){
       longNode = longNode.getNext();
       shortNode = shortNode.getNext();
     }
     return longNode;
  }

  public static int getListNodeLength(ListNode listNode){
     if(listNode==null)
       return 0;
     int i=1;
     while (listNode.getNext()!=null){
       listNode = listNode.getNext();
       i++;
     }
     return i;
  }
}
题目:在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
package algorithm;

import java.util.HashMap;
import java.util.Map;

/**
 * author : fzy
 * date   : 2019/11/30 8:46
 * desc   : 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
 */
public class demo17 {
  public static void main(String[] args) {
   System.out.println(FirstNotRepeatingChar("qaCkq"));
  }
  //FirstNotRepeatingChar()根据分割后的数组个数不能适用于重复字母在最后一位的情况,如:qaCkq
  public static int FirstNotRepeatingChar(String str) {
    if (str == null || str.length() == 0) {
      return -1;
    }
    for (int i = 0; i < str.length(); i++) {
      char c = str.charAt(i);
      String[] arr = str.split(String.valueOf(c));
      if (arr.length == 2) {
        return i;
      }
    }
    return -1;
  }

  
      public static int FirstNotRepeatingChar1(String str) {
       if (str == null || str.length() == 0) {
      return -1;
    }
    for (int i = 0; i < str.length(); i++) {
      char c = str.charAt(i);
      String[] arr = str.split(String.valueOf(c));
      if (arr.length == 2&&str.charAt(str.length()-1)!=c) {
        return i;
      }
    }
    return -1;
  }

  public static int FirstNotRepeatingChar2(String str) {
    if (str == null || str.length() == 0) {
      return -1;
    }
    Map<Character,Integer> map = new HashMap<Character,Integer>();
    for(int i=0;i<str.length();i++){
      if(map.containsKey(str.charAt(i))){
        int val = map.get(str.charAt(i));
        map.put(str.charAt(i),val+1);
      }else{
        map.put(str.charAt(i),1);
      }
    }
    for(int i=0;i<str.length();i++){
      if(map.get(str.charAt(i))==1){
        return i;
      }
    }
    return -1;
  }

//在牛客网测试性能最优
 public static int FirstNotRepeatingChar3(String str) {
       if (str == null || str.length() == 0) {
      return -1;
    }
    HashSet<Character> set = new HashSet<>();
    for(int i=0;i<str.length();i++){
      for(int j=i+1;j<str.length();j++){
        if(str.charAt(i)==str.charAt(j)){
          set.add(str.charAt(i));
          break;
        }else if(j==str.length()-1&&!set.contains(str.charAt(i))){
          return i;
        }
      }
    }
    return -1;
  }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值