排序
1. 冒泡排序(O(n2))
把最大的沉到最后,两两交换
public void bubbleSort(int[] nums) {
// 外层循环控制排序的轮数
for (int i = nums.length - 1 ; i > 0; i--) {
boolean isSorted = true;
// 内层循环每次将未排序序列中最大的数冒泡到最后端
for (int j = 0; j < i;j++) {
// 升序
if (nums[j] > nums[j+1]) {
swap(nums,j,j+1);
isSorted = false;
}
}
if (isSorted) {
break;
}
}
}
2. 快速排序(O(nlogn))
哨兵
public void quickSort(int[] nums,int l, int r) {
if (l < r) {
int q = partition(nums,l,r);
quickSort(nums,l,q-1);
quickSort(nums,q+1,r);
}
}
private int partition(int[] nums, int l, int r) {
// 临界值,哨兵
int tmp = nums[l];
int i = l, j = r;
while (i != j) {
// 都带等号
while (i < j && tmp <= nums[j]) {
j--;
}
while (i < j && tmp >= nums[i]) {
i++;
}
if (i < j) {
swap(nums,i,j);
}
}
// 将基准数归位,放在中间位置
nums[l] = nums[i];
nums[i] = tmp;
return i;
}
3. 选择排序(O(n2))
每次选出最小的放到端点处
public void selectSort(int[] nums) {
for (int i = 0 ; i < nums.length; i++) {
int index = i;
for (int j = i+1; j < nums.length;j++) {
// 找出最小的,放在端点处
if (nums[j] < nums[index]) {
index = j;
}
}
swap(nums,i,index);
}
}
4. 插入排序(O(n2))
把当前的数(nums[i])插入到之前已经排好序的数组中
public void insertSort(int[] nums) {
for (int i = 1; i < nums.length; i++) {
int tmp = nums[i];
int j = i;
while (j > 0 && nums[j-1] > tmp) {
nums[j] = nums[j-1];
j--;
}
nums[j] = tmp;
}
}
5. 二分插入排序(O(nlogn))
public void binaryInsertSort(int[] nums) {
for (int i = 1; i < nums.length; i++) {
int tmp = nums[i];
int l = 0, r = i-1;
// l <= r
while (l <= r) {
int mid = l + (r-l)/2;
if (nums[mid] < tmp) {
l = mid + 1;
}
else {
r = mid - 1;
}
}
// 要插入的位置之后的都后移
for (int j = i - 1;j >= l; j--) {
nums[j+1] = nums[j];
}
// 插入
nums[l] = tmp;
}
}
链表:
1. 判断相交
相同的尾节点
2. 找到交点
也可以:假设第一个链表长度为len1,第二个问len2,然后找出长度较长的,让长度较长的链表指针向后移动|len1 - len2| (len1-len2的绝对值),然后在开始遍历两个链表,判断节点是否相同即可。
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode l1 = pHead1, l2 = pHead2;
while (l1 != l2) {
l1 = (l1 == null) ? pHead2 : l1.next;
l2 = (l2 == null) ? pHead1 : l1.next;
}
return l1;
}
3. 判断环
快慢指针
4. 找到环的入口
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if (pHead == null || pHead.next == null || pHead.next.next ==null) {
return null;
}
ListNode fast = pHead.next.next;
ListNode slow = pHead.next;
// 判断有环
while (slow != fast) {
if (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
else {
return null;
}
}
fast = pHead;
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
5. 链表反转
public ListNode ReverseList(ListNode head) {
ListNode pre = null, next = null, reverseHead = null;
ListNode pNode = head;
while (pNode != null) {
next = pNode.next;
pNode.next = pre;
pre = pNode;
pNode = next;
if (pNode == null) {
reverseHead = pre;
}
}
return reverseHead;
}
6. 删除链表中的重复节点
新建一个头结点,防止第一个数就重复;用pre指针保存前一个节点;直接比较pnode.next.val == pnode.val,直到找到最后一个相等的值
public ListNode deleteDuplication(ListNode pHead)
{
if (pHead == null || pHead.next == null) {
return pHead;
}
ListNode newHead = new ListNode(-1);
newHead.next = pHead;
ListNode pre = newHead;
ListNode pNode = newHead.next;
while (pNode != null) {
if (pNode.next != null && pNode.val == pNode.next.val) {
// 找到最后一个相同的节点
while (pNode.next != null && pNode.val == pNode.next.val) {
pNode = pNode.next;
}
pre.next = pNode.next;
pNode = pNode.next;
}
else {