数据结构基础知识(二)

1.      如何从尾到头输出单链表

方法一思想:从头到尾遍历链表,没经过一个结点,把该节点放到一个栈中。当遍历完整个链表后,再从栈顶开始输出结点的值。

 更高效的方法:递归方法实现,每访问到一个结点,先递归输出它后面的节点,再输出该节点自身,这样链表的输出结果就反过来了。

publicvoidprintListReversely(Node<String> pListHead){

           if(pListHead!=null){

                  printListReversely(pListHead.next);

                  System.out.print(pListHead.data+" ");

           }

    }

2.       如何寻找单链表的中间结点

首先设置两个指针,快的指针每次走两步,慢的指针每次走一步.直到快的指针指向链表尾部,这时慢的指针(奇数)指向中间结点或者(偶数)指向中间两个结点中的前一个。

public Node<String>SearchMid(Node<String> head){

           Node<String>p=this.head;

           Node<String>q=this.head;

           while(p!=null&&p.next!=null&&p.next.next!=null){

                  p=p.next.next;

                  q=q.next;

           }

           return q;

    }

3.       如何测试一个链表是否有环

同样定义两个指针,fast和slow,slow每次前进一步 ,fast每次前进两步。同时还要比较fast和low是否相等,如果相等说明有环。

publicbooleanisLoop(Node<String> head){

           Node<String>fast=head;

           Node<String>slow=head;

           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<String>FindLoopPort(Node<String> head){

           Node<String>slow=head,fast=head;

           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;

    }

4.      各种排序算法的性能比较

                
   除上述排序算法之外还有,位图排序(当排序数据规模巨大是,对内存没有限制,选择位图排序),桶排序,基数排序。


5.      如何判断一个数是否是2的n次方

用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));

    }

}

6.      如何求二进制数中1的个数

给定一个数,输出这个整数二进制表示中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的个数。

7.     如何寻找数组中的最大值和最小值

有五种方法:

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<len-1;i=i+2){

                       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]<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);

     }

}

8.      如何寻找数组中重复元素最大的数

对于数组[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<Integer,Integer>m=new HashMap<Integer,Integer>();

              for(int i=0;i<size;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<Entry<Integer,Integer>> iter=m.entrySet().iterator();

              while(iter.hasNext()){

                       Map.Entry<Integer,Integer>entry=(Map.Entry<Integer,Integer>) iter.next();

                       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);

     }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值