方法一思想:从头到尾遍历链表,没经过一个结点,把该节点放到一个栈中。当遍历完整个链表后,再从栈顶开始输出结点的值。
更高效的方法:递归方法实现,每访问到一个结点,先递归输出它后面的节点,再输出该节点自身,这样链表的输出结果就反过来了。
publicvoidprintListReversely(Node
if(pListHead!=null){
printListReversely(pListHead.next);
System.out.print(pListHead.data+" ");
}
}
首先设置两个指针,快的指针每次走两步,慢的指针每次走一步.直到快的指针指向链表尾部,这时慢的指针(奇数)指向中间结点或者(偶数)指向中间两个结点中的前一个。
public Node
Node
Node
while(p!=null&&p.next!=null&&p.next.next!=null){
p=p.next.next;
q=q.next;
}
return q;
}
同样定义两个指针,fast和slow,slow每次前进一步 ,fast每次前进两步。同时还要比较fast和low是否相等,如果相等说明有环。
publicbooleanisLoop(Node
Node
Node
if(fast==null){
returnfalse;
}
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
if(fast==slow){
returntrue;
}
}
return !(fast==null||fast.next==null);
}
寻找环的入口点。
图中可以得到,起点到环入口距离a=(n-1)环长r+环入口到相遇点距离x(L-a-x)。针对于fast指针走的距离来计算的。于是在链表头与相遇点分别设计一个指针,每次各走一步,两个指针必定相遇,且相遇第一点在环入口点。
public Node
Node
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
if(slow==fast)break;
}
if(fast==null||fast.next==null){
returnnull;
}
slow=head;
while(slow!=fast){
slow=slow.next;
fast=fast.next;
}
return slow;
}
除上述排序算法之外还有,位图排序(当排序数据规模巨大是,对内存没有限制,选择位图排序),桶排序,基数排序。
用1做移位操作,然后判断移位后的值是否与给定的数相等。高效的算法:由于2的n次方二进制的表示只有最高位是1(比如16:10000),其余全部是0。如果一个数的二进制表示只有一位是1,如num=00010000,那么num-1的二进制为00001111,由于num与num-1二进制表示中每一位都不相同,因此num&(num-1)的运算结果为0,可以利用这种方法来判断。
publicclass Test {
publicstaticboolean isPower(int n){
if(n<1)returnfalse;
int m=n& (n-1);
return m==0;
}
publicstaticvoid main(String[] args) {
System.out.println(isPower(45));
System.out.println(isPower(32));
}
}
给定一个数,输出这个整数二进制表示中1的个数,具体思路:首先判断这个数的最后一位是否为1,然后通过右移丢弃最后一位。如此循环执行该操作,直到这个数等于0.
publicstaticint countOne(int n){
int count=0;
while(n>0){
if(n!=0){
n=n&(n-1);
count++;
}
}
return count;
}
时间复杂度为O(m),m为二进制数中1的个数。
有五种方法:
1) 将问题看做两个独立的问题,遍历两次数组,分别找出最大值和最小值.比较2N次.
2) 取单元素法,维持两个变量min和max,每次取出一个元素,先与已找到的最小值比较,再与已找到的最大值比较。遍历一次数组。
3) 取双元素法,维持两个变量min和max,每次比较相邻两个数,较大者与max比较,较小者与min比较。比较次数为1.5N次。
4) 数组元素移位法,将数组中相邻的两个数分在一组,每次比较两个相邻的数,大的放在左边,小的放在右边。然后分别扫描大、小数组,找出最大值和最小值。比较此时1.5N~2N,同时改变了数组结构。
5) 分治法,将数组分为两半,分别找出最大值和最小值。整个数组的最大值就是两个子数组中的最大值。同理找出最小值。遍历次数1.5N。
public class Maxmin {
static int Max;
static int Min;
public static void GetMaxAndMin(int a[]){
Max=a[0];
Min=a[0];
int len=a.length;
for(int i=1;i
if(i+1>len){
if(a[i]>Max){
Max=a[i];
}
if(a[i]<Min){
Min=a[i];
}
}
if(a[i]>a[i+1]){
if(a[i]>Max){
Max=a[i];
}
if(a[i+1]<Min){
Min=a[i+1];
}
}
if(a[i+1]>Max){
Max=a[i+1];
}
if(a[i]<Min){
Min=a[i];
}
}
}
}
public static void main(String[] args) {
int[] a={7,2,34,18,43,4,7,1};
GetMaxAndMin(a);
System.out.println("Max="+Max);
System.out.println("Min="+Min);
}
}
对于数组[1,1,2,2,4,4,5,5,5,5,5,6,6,6],元素5出现的此时最多,所以应该输出5。
方法一:空间换时间。定义一个数组 int count[Max],并将其数组元素都初始化为0,然后执行for(inti=0;i<100;i++)count[a[i]]++操作,在count数组中找到最大的数,
方法二: 使用Map映射表。通过引入Map映射表来记录每个元素出现的次数,然后判断次数大小,进而找出重复次数最多的元素。
public class Maxnumber {
public static int findMostFrequentInArray(int a[]){
int result=0;
int size=a.length;
if(size==0){
return Integer.MAX_VALUE;
}
//记录每个元素出现的次数
Map
for(int i=0;i
if(m.containsKey(a[i])){
/*
* 此实现在 entrySet() 上进行迭代,以搜索带有指定键的条目。如果找到这样的条目,
* 则返回该条目的值。如果迭代终止,并且没有找到这样的条目,则返回 null。
* 注意,此实现所需的时间与映射的大小呈线性关系;许多实现将重写此方法。
*/
m.put(a[i],m.get(a[i])+1);
}
else{
m.put(a[i],1);
}
}
//找出出现次数最多的元素
int most=0;
Iterator
while(iter.hasNext()){
Map.Entry
int key=(Integer) entry.getKey();
int val=(Integer) entry.getValue();
if(val>most){
result=key;
most=val;
}
}
return result;
}
public static void main(String[] args) {
int a[]={1,5,4,3,4,4,5,4,5,5,3,4,6,6,7};
int maxFrequenceNum=findMostFrequentInArray(a);
System.out.println(maxFrequenceNum);
}
}