时间复杂度:主要看常数操作得到的表达式中去了常数项的最高项;
空间复杂度:如果只是开辟了几个简单的变量空间,则复杂度为O(1);
选择排序
#include<stdio.h>
int select(int a[], int n)
{
int i, j, min;
for(i = 0; i < n - 1; i++)
{
min = i;
for(j = i + 1; j < n; j++)
{
min = a[j] < a[min] ? j : min;
}
int t;
t = a[min];
a[min] = a[i];
a[i] = t;
}
for(i = 0; i < n; i++)
{
printf("%d", a[i]);
}
}
int select2(int a[], int n)
{
int i, j;
for(i = 0; i < n; i++)
{
for(j = i + 1; j < n; j++)
{
if(a[j] < a[i])
{
a[i] = a[i] ^ a[j];
a[j] = a[i] ^ a[j];
a[i] = a[i] ^ a[j];
}
}
}
for(i = 0; i < n; i++)
{
printf("%d", a[i]);
}
}
int main()
{
int n, i;
scanf("%d", &n);
int a[n];
for(i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
select(a, n);
printf("\n");
select2(a, n);
}
异或运算
^同零异一
也可以理解为无进位相加
性质
一, 0 和任何数异或都等于任何数, 任何数和自己异或都等于任何数
二,满足交换率和结合律
三,同一批数异或结果一样,无论顺序
if(a[j] < a[i])
{
//通过异或运算来交换两个数
a[i] = a[i] ^ a[j];
a[j] = a[i] ^ a[j];
a[i] = a[i] ^ a[j];
}
原理解释
前提是 a, b指向的内存地址不同
如果a,b指向内存相同的话,三行代码出来就是0
关于异或的面试题
一, 在一组数中,只有一种数出现奇数次,其他数都出现偶数次,
请找出出现奇数次的数。
解析:用0异或这组数,因为异或一组数的结果是唯一的与数的位置无关,所以把相同的数异或,出现偶数次数的数异或为0,出现奇数次数的数异或为改奇数,最后0和该奇数异或为该奇数。
int [1,1,1,1,3,3,3,2,2]
int e = 0;
e = e ^ i
异或运算同一批数,无论数的顺序,最终结果相同
问题二:只有两种数出现了奇数次,剩下的数都出现了偶数次
找出出现了奇数次的数
假设这两种数分别为a 和 b
如果用一个为0的变量eor从头异或到尾,最后得到的是a 异或 b, 且 a 不等于 b,
那么eor就不等于0
插入排序
插入排序的时间复杂度受到数据状况的影响,但冒泡排序和选择排序不受影响
插排的时间复杂度按照最差的数据状况来估计
一般来说插排的效率比冒泡和选择排序高,因为其余二者都是严格的O(n平方)
插入排序:一个指标指定元素,看该元素前一位,如果比它小则交换二者,重复操作直到元素有序
public class Insertsort {
public void insert(int arr[]) {
if(arr == null || arr.length < 2) {
return;
}
for(int i = 1; i < arr.length; i++) {
for(int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
swap(arr, j, j-1);
}
}
}
public void swap(int arr[], int a, int b) {
arr[a] = arr[a] ^ arr[b];
arr[b] = arr[a] ^ arr[b];
arr[a] = arr[a] ^ arr[b];
}
}
认识时间复杂度
二分查找
效率 log 2为底 N
一般写为logN就代表 log 2为底 N
找到大于某个数的最左侧的位置也可以用二分
局部最小值问题也可以用二分
n个元素局部最小:
对于0位置的元素只需比1位置小
对于n-1位置元素只需比n-2位置的小
对于i位置需要比i-1和i+1的小