常见算法

排序&查找

二分查找

题目:在有序数组中查找一个值,返回该值的索引。(非递归方式&递归方式)

//非递归方式
public static int binaryFind(int[] list, int value) {
    int left = 0;
    int right = list.length - 1;
    int mid;
    while (left <= right) {// 当最小索引大于最大索引时,那么一定没有这个数了
        // mid = (left + right) / 2;//(不建议这样取中,因为可能数太大超出范围)
        // mid = left + ((right - left) >> 1);
        mid = left + (right - left) / 2;// 中间索引
        if (value == list[mid]) {//找到之后返回索引
            return mid;
        } else if (value > list[mid]) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;// 没有找到,返回-1
}
//递归方式
public static int binaryFind2(int[] list, int value, int left, int right) {
    if (left <= right) {
        int mid = left + (right - left) / 2;
        if (list[mid] == value) {
            return mid;
        } else if (list[mid] > value) {
            return binaryFind2(list, value, left, mid - 1);
        } else {
            return binaryFind2(list, value, mid + 1, right);
        }
    } else
        return -1;
}

冒泡排序(优化后)

O(N^2) 时间

public static int[] bubbleSort(int[] a) {
    int leng = a.length;
    for (int i = 0; i < leng; i++) {
        boolean flag = true;
        for (int j = 0; j < leng - i - 1; j++) {
            if (a[j] > a[j + 1]) {
                int tem = a[j];
                a[j] = a[j + 1];
                a[j + 1] = tem;
                flag = false;
            }
        }
        if (flag) {
            break;
        }
        System.out.println("排序次数:" + i);
    }
    return a;
}

选择排序

O(N^2) 时间(每次选择最小的或最大的来生成一个数组)

public static int[] ChoiceSort(int[] a) {
    for (int i = 0; i < a.length; i++) {
        int min = i;
        for (int j = i + 1; j < a.length; j++) {
            if (a[min] > a[j]) {
                min = j;
            }
        }
        int tem = a[i];
        a[i] = a[min];
        a[min] = tem;
        //display(a);
    }
    return a;
}

快速排序

平均O(NLogN) 时间()

public static void sort(int[] list, int left, int right) {
    int division = division(list, left, right);
    if (left < right) {
        sort(list, left, division - 1);
        sort(list, division + 1, right);
    }
}

public static int division(int[] list, int left, int right) {
    int base = list[left];
    while (left < right) {
        while (left < right && list[right] >= base) {
            right--;
        }
        list[left] = list[right];
        while (left < right && list[left] <= base) {
            left++;
        }
        list[right] = list[left];
    }
    list[left] = base;
    return left;
}

反转字符串(多种方法)

方法1:利用栈实现

String str = "how are you";
Stack stack = new Stack();
char[] ch = str.toCharArray();
for (char c : ch) {
    stack.push(c);
}
while (!stack.isEmpty()) {
    System.out.print(stack.pop());
}

方法2.1:通过数组

public static String fanzhuan(String str) {
    if ("".equals(str)) {
        return "";
    }
    int len = str.length();
    char[] s = str.toCharArray();
    for (int i = 0; i < len ; i++) {
        s[i] = str.charAt(len - i - 1);
    }
    return new String(s);
}
//方法2.2:通过数组(减少一半)
public static String fanzhuan(String str) {
    if ("".equals(str)) {
        return "";
    }
    int len = str.length();
    char[] s = str.toCharArray();
    for (int i = 0; i < len / 2; i++) {
        s[i] = str.charAt(len - i - 1);
        s[len - 1 - i] = str.charAt(i);
    }
    return new String(s);
}
//方法3:使用StringBuilder逆序遍历
//方法4:使用递归
public static String reverse(String str) {
    if ("".equals(str))
        return "";
    int len = str.length();
    if (len == 1) {
        return str;
    }
    return reverse(str.substring(1)) + str.charAt(0);
}

Top k问题(多种方法)

堆排序之后取前k个:O(NlogN)

代码直接看堆排序即可

利用堆排序:O(NlogK)

伪代码:
heap[k] = make_heap(arr[1, k]);
for(i=k+1 to n){
         adjust_heap(heep[k],arr[i]);
}
return heap[k];
public static int[] top(int[] list, int k) {
    if (list.length <= k) {
        return list;
    }
    int[] array = new int[k];
    for (int i = 0; i < k; i++) {
        array[i] = list[i];
    }
    headSort(array);
    for (int i = k; i < list.length; i++) {
        if (array[0] < list[i]) {
            array[0] = list[i];
            headSort(array);
        }
    }
    return array;
}

public static int[] headSort(int[] inputList) {// 堆排序
    int length = inputList.length;
    for (int i = length / 2; i >= 0; i--) {// 建立初始堆
        heap(inputList, i, length);
    }
    for (int i = length - 1; i >= 0; i--) {// n-1次循环完成排列
        // 将最后一个元素和第一个元素进行交换(第一个元素是最大的,交换位置后,最大的就在排最后了)
        int tem = inputList[i];
        inputList[i] = inputList[0];
        inputList[0] = tem;
        heap(inputList, 0, i);// 将inputList中前i个记录重新调整为大顶堆
    }
    return inputList;
}

public static void heap(int[] list, int parent, int len) {// 构建堆
    int tem = list[parent];
    int child = 2 * parent + 1;
    while (child < len) {
        if (child + 1 < len && list[child + 1] > list[child]) {
            child++;
        }
        if (list[child] <= tem) {
            break;
        }
        list[parent] = list[child];
        parent = child;
        child = 2 * parent + 1;
    }
    list[parent] = tem;
}

使用优先队列PriorityQueue

(PriorityQueue就是通过堆实现的)

public static int[] topk(int[] list, int k) {
    if (list.length <= k) {
        return list;
    }
    PriorityQueue<Integer> pq = new PriorityQueue<>(k, new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 - o2;//最大堆
            //return  o2 - o1;//最小堆
        }
    });
    for (int num : list) {
        if (pq.size() < k) {
            pq.offer(num);
        } else if (pq.peek() < num) {
            pq.poll();
            pq.offer(num);
        }
    }
    int[] array = new int[k];
    for (int i = 0; i < k; i++) {
        array[i] = pq.poll();
    }
    return array;
}

动态规划

最长公共子串与最长公共子序列

最长公共子串与最长公共子序列(动归实现)

连续子数组的最大和

该算法在每次元素累加和小于0时,从下一个元素重新开始累加。实现代码如下:

public static int sum(int[] list) {
    int maxSum = 0;//记录最大的值
    int cursum = 0;//记录 暂时累加和
    for (int i = 0; i < list.length; i++) {
        cursum += list[i];
        if (cursum > maxSum) {//如果 暂时累加 大于历史最大值,则保存
            maxSum = cursum;
        }
        if (cursum < 0) {//如果 暂时累加和 小于0,则将暂时累加和更新为0
            cursum = 0;
        }
    }
    return maxSum;
}

链表

反转链表

    public static Node reverseListNode(Node head) {
        if (head == null || head.next == null) {// 单链表为空或只有一个节点,直接返回原单链表
            return head;
        }
        Node preNode = null;// 前一个节点指针
        Node curNode = head;// 当前节点指针
        Node nextNode = null;// 下一个节点指针
        while (curNode != null) {
            nextNode = curNode.next;// nextNode 指向下一个节点
            curNode.next = preNode;// 将当前节点next域指向前一个节点
            preNode = curNode;// preNode 指针向后移动
            curNode = nextNode;// curNode指针向后移动
        }
        return preNode;
    }

链表中倒数第k个结点

    public static Node findKthToTail(Node node, int k) {
        if (node == null || k == 0) {
            return null;
        }
        Node head = node;
        Node behind = node;
        for (int i = 0; i < k-1; i++) {
            if(head.next==null){
                return null;
            }
            head=head.next;
        }
        while(head.next!=null){
            head=head.next;
            behind=behind.next;
        }
        return behind;
    }

链表中环的入口结点

public static Node entryNodeOfLoop(Node node) {
        if (node == null || node.next == null) {
            return null;
        }
        Node fast = node;
        Node slow = node;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                fast = node;
                while (fast != slow) {
                    fast = fast.next;
                    slow = slow.next;
                }
                if(fast==slow){
                    return slow;
                }
            }
        }
        return null;
    }

二叉树

判断二叉树是否平衡

//class Tree {
//  int value;
//  Tree left;
//  Tree right;
//
//  public Tree(int value) {
//      this.value = value;
//      left = null;
//      right = null;
//  }
//}

public static boolean isBalance(Tree tree) {
    if (tree == null) {
        return true;
    }
    int left = treeDepth(tree.left);
    int right = treeDepth(tree.right);
    int diff = right - left;
    if (diff > 1 || diff < -1) {
        return false;
    }
    return isBalance(tree.left) && isBalance(tree.right);
}
public static int treeDepth(Tree tree) {//二叉树的深度
    if (tree == null) {
        return 0;
    }
    int left = treeDepth(tree.left);
    int right = treeDepth(tree.right);
    return left > right ? left + 1 : right + 1;
}

寻找二叉搜索树第k个结点

public static TreeNode findKthNode(TreeNode root, int k) {
TreeNode target=null;
if(root.left!=null){
target=findKthNode(root.left,k)
}
if(){
}
if(root.right!=null){
target=findKthNode(root.right,k)
}
}

贪心

买卖股票的最佳时机

找到局部最优解,然后再得到整体的最优解。我们可以从第一天的股票价钱出发,和第二天的对比,如果第二天比第一天价格更高了(稳赚),就赶紧买进第1天的,然后第二天卖出。同理,到了第二天,我就和第三天的价格做对比,只要后一天的价格高于今天的,我就买进今天的股票,到后一天再卖出。赚到的钱依次相加,得到最大的利润。当然如果后一天的价格比今天的低,我们就不买。

    public static int price(int[] list) {
        int result = 0;
        for (int i = 1; i < list.length; i++) {
            result = Math.max(result + list[i] - list[i - 1], result);
        }
        return result;
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349