关于算法与数据结构的一些感想

前言:刚刚参加工作一年的小菜鸟一枚,最近在研究常用的算法与数据结构,作为自己的笔记兼总结,如果有错误之处希望大家能够不吝赐教,谢谢。

1.研究对象
数据的逻辑结构,数据的物理存储结构,算法

基本逻辑结构有四种:
(1)集合—数据结构元素之间除了同属一个集合,再也没有其他关系
(2)线性结构—元素之间存在一对一的相互关系
(3)树形结构—元素之间存在一对多的相互关系
(4)图形结构—元素之间存在多对多的相互关系

数据的物理存储结构
顺序存储:地址连续,可以用公式很快确定任意元素存储位置/逻辑上相邻的元素,物理位置上也是临接的。
优点:随机的取元素比较容易,可以根据下标通过公式计算。
缺点:
(1)插入和删除节点比较困难,由于是依次连续存放的,必须将插入节点之后的节点位置依次移动。
(2)不易扩展,主要是由于 地址空间
(3)易造成浪费,也是由于地址空间

链式存储:地址不连续,存放的不止有数据,还有指针,若要确定某一元素位置,必须从第一个元素开始顺藤摸瓜。

时间复杂度:
运算时间是指一个算法在计算机上运行所需要话费的时间,算法执行时间为简单操作的次数(比如赋值,转向,比较等)以及单次简单操作的执行时间的乘积,而简单操作的执行时间是由计算机系统决定的,因此算法时间与简单操作的次数成正比。。。一般来说,把算法中包含简单操作的次数称为算法的时间复杂性,记为T(n)

计算时间复杂性需要把操作拆分为简单操作:
示例代码:

    public void test()
    {
        int s = 0;
        for (int i = 0 ;i < n; i++)
        {
            s = s + i;
        }
        return s;       
    }

拆分为简单操作:

    public void test()
    {
        int s = 0;     //   1
        int i = 0;     //1
        while (i < n)  // n+1
        {
            s = s + i;  //  n
            i++;     // n
        }
        return s;     // 1
    }

时间复杂性为:T(n) = 3n+4

当n趋于无穷大时,把时间复杂性T(n)的数量级O(f(n))称为算法的时间复杂度

2.线性表

顺序表:在逻辑上相邻 的数据元素,他们的物理位置也是临接的。
链表:节点在存储器中的位置是任意的,节点之间的逻辑关系由节点中的指针来指示(单链表,循环链表,双向链表)

数组算法题:
1. 两数之和
给定一个整型数组,是否能找出其中两个数使其和为某个指定的值
先看输入,输入是否有序?先假定无序

自己写的:

package suanfa;
public class SumOfTwoNums {
    public static void main(String[] args) {
        test(new int[]{1,2,3,4,5}, 7);
    }

    public static void test(int [] arrs, int sum)
    {
        if (arrs.length < 2)
        {
            System.out.println("not exist...");
            return;
        }
        for (int i = 0; i < arrs.length; i ++)
        {
            for (int j =  i + 1; j < arrs.length; j ++)
            {
                if (arrs[i] + arrs[j] == sum)
                {
                    System.out.println("arrs[" + i + "]" + "= " + arrs[i] + ", arrs[" + j + "]" + "= " + arrs[j]);
                    break;
                }               
            }
        }
    }
}

很明显这个是我们最开始想到的办法,他的时间复杂度为O(n^2),有点高啊,说明它还是有优化空间滴。。。。

人家的解法:现将数组排序,首尾各一个指针向中间移动,直到找到和为止,代码的时间复杂度为O(nlogn)。

public static void main(String[] args) {
        test(new int[]{1,2,3,4,5}, 7);
    }

    public static void test1(int [] arrs, int sum)
    {
        if (arrs.length < 2)
        {
            System.out.println("not exist...");
            return;
        }
        Arrays.sort(arrs);

        int i = 0;
        int j = arrs.length - 1;
        while (i < j)
        {
            if (arrs[i] + arrs[j] == sum)
            {
                System.out.println("arrs[" + i + "]" + "= " + arrs[i] + ", arrs[" + j + "]" + "= " + arrs[j]);
                if (j - i == 1)
                {
                    break;
                }
                else
                {
                    i ++;
                    j --;
                }
            }
            else if (arrs[i] + arrs[j] < sum)
            {
                i ++;
            }
            else
            {
                j ++;
            }
        }
    }

接下来,若还需要降低时间复杂度,要求时间复杂度为O(n),我的天!遍历一遍数组就需要O(n)了,还好给定了额外的条件,值
互不相同,且可以使用额外的空间,嗯,可以使用哈希表

public static void main(String[] args) {
        test2(new int[]{1,2,3,4,5}, 7);
    }

    public static void test2(int [] arrs, int sum)
    {
        if (arrs.length < 2)
        {
            System.out.println("not exist...");
            return;
        }

        Map map = new HashMap();

        //这个list是为了去重
        List list = new ArrayList();

        for (int i = 0; i< arrs.length; i ++)
        {
            map.put(arrs[i], i);
        }
        for (Map.Entry entry : map.entrySet())
        {
            int key = entry.getKey();
            list.add(key);
            int otherValue = sum - key;
            if (map.containsKey(otherValue))
            {
                int index  = map.get(otherValue);

                if (!(list.contains(key) && list.contains(otherValue)))
                {
                    list.add(otherValue);
                    System.out.println("arrs[" + map.get(key) + "]" + "= " + key + ", arrs[" + index + "]" + "= " + otherValue);
                }
            }
        }
    }

接下来,若里面允许有重复的元素,算法又不一样了。因为map中的key值是不允许重复的,可以使用hashMap来存储值与值出现的次数。但是有一点需要重点考虑一下,如果目标值恰好是和的两倍,这个特殊情况需要考虑到。

  1. 数组旋转,返回将某一维数组想右旋转K个位置的结果,例如一维数组{1,2,3,4,5},旋转3个位置即为:{3,2,1,4,5}

首先想到的最正常的解法:

public static void main(String[] args) {
        int [] arr = test4(new int[]{1,2,3,4,5}, 4);;
        for (int i : arr)
        {
            System.out.print(i + ", ");
        }
    }


    public static int[] test4(int [] arrs, int n)
    {
        if (n > arrs.length)
        {
            return null;
        }

        int [] newArr = new int[arrs.length];

        for (int i = 0; i < n; i ++)
        {
            newArr[i] = arrs[n - i - 1];
        }

        for (int j = n; j < newArr.length; j ++)
        {
            newArr[j] = arrs[j];
        }

        return newArr;
    }

输出:

4, 3, 2, 1, 5, 

未完待续。。。。

你可能感兴趣的:(算法与数据结构)